Why don't these threads run in sequence? [duplicate] - java

This question already has answers here:
Synchronized block not working
(8 answers)
Closed 7 years ago.
I have difficulty understanding synchronized and reentrant lock. Here is small program I was experimenting with:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Reentr {
public static void main(String[] args) {
ExecutorService eService = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 2; i++) {
eService.execute(new process());
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
eService.shutdown();
}
}
class process implements Runnable {
int count = 0;
#Override
public void run() {
processTest();
}
public synchronized void processTest() {
try {
for (int i = 1; i <= 2; i++) {
count += i;
System.out.println("count value for " + Thread.currentThread().getName() + " is " + count);
}
} finally {
System.out.println("count for " + Thread.currentThread().getName() + " is " + count);
}
}
}
The output was:
count value for pool-1-thread-2 is 1
count value for pool-1-thread-1 is 1
count value for pool-1-thread-2 is 3
count for pool-1-thread-2 is 3
count value for pool-1-thread-1 is 3
count for pool-1-thread-1 is 3
If we see in the output two thread are in the synchronized block. I was under the impression that one thread has to complete the execution of synchronized method, after that other thread will enter the method.
Ideally, I was expecting result something like this
count value for pool-1-thread-1 is 1
count value for pool-1-thread-1 is 3
count for pool-1-thread-1 is 3
count value for pool-1-thread-2 is 1
count value for pool-1-thread-2 is 3
count for pool-1-thread-2 is 3
I have replaced synchronized method with synchronized block and re-entrant locks. However, I still have the same output. What am I missing?

The two threads are not synchonizing on the same object.
You have two different instances of process (as an aside; you should always name classes with a Capital letter). The synchronized keyword is equivalent to:
public void processTest() {
synchronized(this) {
// etc..
}
}
If you want one thread to run after the other, they must synchronize on the same object. If you did this, for example:
class process implements Runnable {
// note that this is static
private static final Object lock = new Object();
public void processTest() {
synchronized(lock) {
// your code
}
}
}
Then your code would have one thread run after the other. Another way to do it would be to pass the lock into the Objects constructor, or the same instance of a Semaphore, etc.

When an instance method is declared synchronized, it synchronizes on the object instance. Since you are running with a new process() in each loop iteration, the object instances are different, so the synchronization is meaningless. Try creating a single process object and passing that to both of the threads you start.
When you do, also move the count instance variable into the processTest method. That way it will be thread safe.

Related

How does incrementing a value across multiple threads in Java work?

I have two pieces of multithreaded code. One passes an Integer to the thread and the thread increments it and the other passes an object that has an inner Integer which is incremented. When I run these the output is different and not what I expected. Can someone give an explanation of what's going and how I'd make the first behave in a similar manner to the second.
Implementation 1:
public class Main {
public static void main(String[] args) {
Integer counter = 0;
for (int i = 0; i < 3; i++) {
Threaded t = new Threaded("Thread " + i, counter);
Thread thread = new Thread(t);
thread.start();
}
}
}
class Threaded implements Runnable {
private final String name;
private Integer counter;
public Threaded(String name, Integer counter) {
this.name = name;
this.counter = counter;
}
#Override
public void run() {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println(name + ": " + counter);
}
}
}
Output 1:
Thread 1: 1
Thread 1: 2
Thread 0: 1
Thread 0: 2
Thread 0: 3
Thread 0: 4
Thread 0: 5
Thread 2: 1
Thread 2: 2
Thread 2: 3
Thread 2: 4
Thread 1: 3
Thread 1: 4
Thread 1: 5
Thread 2: 5
Implementation 2:
public class Main {
public static void main(String[] args) {
MyObj obj = new MyObj();
for (int i = 0; i < 3; i++) {
Threaded t = new Threaded("Thread " + i, obj);
Thread thread = new Thread(t);
thread.start();
}
}
}
class MyObj {
private int count = 0;
public void inc() { count++; }
public int getCount() { return count; }
}
class Threaded implements Runnable {
private final String name;
private final MyObj obj;
public Threaded(String name, MyObj obj) {
this.name = name;
this.obj = obj;
}
#Override
public void run() {
for (int i = 0; i < 5; i++) {
obj.inc();
System.out.println(name + ": " + obj.getCount());
}
}
}
Output 2:
Thread 1: 2
Thread 1: 3
Thread 1: 4
Thread 1: 5
Thread 1: 6
Thread 0: 1
Thread 0: 7
Thread 2: 8
Thread 0: 9
Thread 2: 10
Thread 2: 11
Thread 0: 12
Thread 2: 13
Thread 2: 15
Thread 0: 14
Is it possible to have multiple threads all increment an Integer directly but get an output similar to implementation 2?
For the first example, each thread has its own counter and it is incremented separately. Integer is immutable, when it is incremented the result is a new Integer object. The threads get the same starting value but there is no shared state.
For the second example the threads share the same MyObject instance, there is nothing to stop them from overwriting each others' work. Use AtomicInteger in the second example and the threads won't interfere with each other.
class MyObj {
private AtomicInteger counter = new AtomicInteger(0);
public void inc() {
counter.incrementAndGet();
}
public int getCount() {
return counter.get();
}
}
Never share unprotected resources across threads
The Answer by Nathan Hughes is correct.
Change this code:
new Threaded( "Thread " + i , obj )
… to this:
new Threaded( "Thread " + i , new MyObject( … ) )
… to get behavior similar to your first example. By passing each new Thread its own instance of MyObject, the various Thread objects will no longer be stepping in each other’s feet.
The lesson here is to never share resources across threads without adding protection. As Nathan Hughes suggested, replacing int on MyObject class with AtomicInteger is one way to add protection. Mark that AtomicInteger as final to ensure that its instance is never replaced.
Executor service
Another issue: In modern Java, we rarely address the Thread class directly. Instead, use the Executors framework added to Java 5.
Define your task as a Runnable or Callable. Pass an instance of that task to an executor service.
The lambda syntax in Java 8+ is often quite convenient to use in defining your Runnable. The code in the lambda can refer to variables in its surrounding code.
This has been covered many times on Stack Overflow. Search to learn more.
Example code
Here is a revamped version of your code using an executor service.
Notice that inc method has been changed to return the newly incremented count rather than returning void. By the time another line of code called the MyObj#getCount, some other thread may have performed an additional increment, so result of getCount would not give your intended results.
package work.basil.threading;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class App2
{
public static void main ( String[] args )
{
App2 app = new App2();
app.demo();
}
private void demo ( )
{
final MyObj myObj = new MyObj();
Runnable task = ( ) -> {
for ( int i = 0 ; i < 5 ; i++ )
{
int newValue = myObj.inc();
// BEWARE: Multi-threaded calls to `System.out` may *not* appear chronologically. Add timestamp to get some idea of chronology.
System.out.println( Thread.currentThread().getId() + " thread incremented to : " + newValue + " at " + Instant.now() );
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
for ( int i = 0 ; i < 3 ; i++ )
{
executorService.submit( task );
}
executorService.shutdown();
try { executorService.awaitTermination( 1 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { throw new RuntimeException( e ); }
}
}
class MyObj
{
private final AtomicInteger count = new AtomicInteger();
public int inc ( ) { return this.count.incrementAndGet(); }
public int getCount ( ) { return count.get(); }
}
Example run. Again, beware of the console printing lines out of chronological order.
15 thread incremented to : 1 at 2022-03-04T21:54:17.926156Z
17 thread incremented to : 3 at 2022-03-04T21:54:17.926207Z
16 thread incremented to : 2 at 2022-03-04T21:54:17.926219Z
17 thread incremented to : 5 at 2022-03-04T21:54:17.941980Z
15 thread incremented to : 4 at 2022-03-04T21:54:17.941961Z
16 thread incremented to : 6 at 2022-03-04T21:54:17.942027Z
15 thread incremented to : 8 at 2022-03-04T21:54:17.942054Z
17 thread incremented to : 7 at 2022-03-04T21:54:17.942041Z
16 thread incremented to : 9 at 2022-03-04T21:54:17.942067Z
15 thread incremented to : 10 at 2022-03-04T21:54:17.942083Z
17 thread incremented to : 11 at 2022-03-04T21:54:17.942126Z
16 thread incremented to : 12 at 2022-03-04T21:54:17.942164Z
15 thread incremented to : 13 at 2022-03-04T21:54:17.942176Z
16 thread incremented to : 15 at 2022-03-04T21:54:17.942254Z
17 thread incremented to : 14 at 2022-03-04T21:54:17.942219Z
In a nutshell: The difference between your two implementations is that your MyObj class is mutable, but Integer is immutable.
In particular, this statement does not do what you seem to think it does:
counter++;
What it does is:
fetch the value of the counter variable, which is a reference to an immutable Integer object.
Get the int value of the Integer object,
Compute a new int value, equal to 1+ the previous value,
Construct a new Integer object with the new value, and finally
Store a reference to the new object into the counter variable.
Since each of your threads has its own counter, and each one constructs its own new sequence of Integer objects to assign to counter, the threads run entirely independent of each other.
In your second example, there is only ever one MyObj instance. Each thread has its own obj variable, but those are all initialized to point to the same instance, and the threads never assign their obj variables: The threads mutate the one shared instance instead.

I don't get how threads work in this case

The following code is shows how no race condition in thread works, but I don't get the difference between with the synchronized and without it. I thought the static variable counter will be added to 20000 anyway but it turned out that without synchronized counter would be less than 20000. Can you please explain how threads work in this case? Also, in Java, are threads are actually not running "concurrently", instead are they taking turns to run for a while?
public class NoRaceCondition implements Runnable {
private static int counter = 0;
private static Object gateKeeper = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new NoRaceCondition());
Thread t2 = new Thread(new NoRaceCondition());
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.printf("counter = %d\n", counter);
}
public void run() {
synchronized (gateKeeper) {
for (int i = 0; i < 10000; i++) {
{
counter++;
}
}
}
}
}
You can think of count++ as 3 separate steps.
read the value of count
increment the value
override count with the new incremented value
When multiple thread execute the above steps concurrently, race conditions may occur. 1 example of race condition is
Let count = 1
Let there be 2 threads named A and B
Thread A reads the value of count and get 1
Thread B reads the value of count and get 1
Thread A increments its value and get 2
Thread B increments its value and get 2
Thread A writes the value to count
count is now 2
Thread B writes the value to count
count is now 2 again when it's expected to be 3 after 2 increments

Printing numbers in loop with two threads

I am trying out codes with multiple threads.
Below is my code:
package com.thread.practice;
public class ThreadPratice1 {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
t1.start();
t2.start();
}
}
package com.thread.practice;
public class MyRunnable implements Runnable {
private static int i = 0;
#Override
public void run() {
for(i = 0; i <10;i++){
System.out.println("Thread: "+ Thread.currentThread().getName()
+" value of i: "+i);
try {
//System.out.println("Thread: "+ i);
Thread.sleep(1000);
//System.out.println("inside runnable: "+Thread.currentThread().getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
But in the output it is always printing the value of i as 0 twice in the beginning.
Output is coming kind of like this:
Thread: Thread 1 value of i: 0
Thread: Thread 2 value of i: 0
Thread: Thread 1 value of i: 2
Thread: Thread 2 value of i: 2
Thread: Thread 1 value of i: 3
Thread: Thread 2 value of i: 4
Thread: Thread 1 value of i: 5
Thread: Thread 2 value of i: 6
Thread: Thread 1 value of i: 7
Thread: Thread 2 value of i: 8
Thread: Thread 1 value of i: 9
May someone please help me in understanding this issue?
Because the value of i at the begging of the execution of the two threads is 0.
In other words, thread one and thread two stared almost at the same time, so the two of them set the i to 0 for the first loop.
for(i = 0; i <10;i++) {
Then the value changes between thread because you made i static. so it will be shared between your two threads.
You made "i" static, which means it will be the same over all threads and objects. Take away the static modifier and your code will work properly.
edit: I misinterpreted what you asked- don't set i to 0 in the for loop, it will look something like this:
for(;i<10;i++) { /*mycode*/}
One of these two is probably what you want anyway, your question was a little bit vague
value of i is incremented by the for loop only after the loop is executed. Execution of for loop takes a finite amount of time. Since you are starting the threads together (almost), both the threads may or may not print i after the other thread has finished one loop. Since you are not doing to ensure thread safety, the result will be unpredictable like the one you got.
First, You shouldn't use the primitive int type for concurrency, it's not thread safe and it maybe will cause Race Condition,
and try to use AtomicInteger to replace int, it's thread safe. the example maybe:
public class ThreadPratice1 {
public static void main(String[] args) {
AtomicInteger number = new AtomicInteger(0);
MyRunnable r = new MyRunnable(number);
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable {
private AtomicInteger number;
public MyRunnable(AtomicInteger number) {
this.number = number;
}
#Override
public void run() {
while (number.get() < 10) {
System.out.println("Thread: " + Thread.currentThread().getName()
+ " value of i: " + number.getAndIncrement());
}
}
}

Why doesn't my thread return from a wait() after calling notifyAll() from another thread? [duplicate]

This question already has an answer here:
Thread not returning after notifyall()
(1 answer)
Closed 7 years ago.
I am trying to create two threads to act as counters. When one thread decrements its counter, it should toggle the value of the shared boolean flag field, call the notifyAll() method and release the other thread from the wait() method being called. The logic field serves as a means to avoid deadlock, i.e. one thread will call the wait() method when the flag field has a value of true, the other thread will call it when the flag field has a value of false. You can see the way I run the threads created from this class, as well as the expected output below. The problem is that both threads get stuck on the wait() method at the same time and only the first line of output goes through.
The expected output:
Thread No.1 4
Thread No.2 4
Thread No.1 3
Thread No.2 3
Thread No.1 2
Thread No.2 2
Thread No.1 1
Thread No.2 1
Thread No.1 0
Thread No.2 0
The actual output:
Thread No.2 4
The counter class:
public class CounterThread implements Runnable {
private long counter;
private static int threadNumber = 0;
private int index = 0;
private static boolean flag = true;
private boolean logic;
public CounterThread(long counter, boolean logic) {
index = ++threadNumber;
this.counter = counter;
this.logic = logic;
}
private synchronized void toggleFlag() {
flag = !flag;
notifyAll();
}
#Override
public synchronized void run() {
while (counter > 0) {
while (flag==logic) {
try {
wait();
} catch (InterruptedException e) {
}
}
counter--;
System.out.println("Thread No. " + index + " " +counter);
toggleFlag();
}
}
}
The way I run it:
public final class CounterThreadRun {
public static void main(String[] args) {
CounterThread counter1 = new CounterThread(5, true);
CounterThread counter2 = new CounterThread(5, false);
Thread thread1 = new Thread(counter1);
Thread thread2 = new Thread(counter2);
thread1.start();
thread2.start();
}
}
Because you're not notifying the thread that is waiting. You're only notifying the current thread, i.e. yourself. You need a shared object, perhaps a static in the class, that is used for both wait() and notifyAll().

counter value is not being implemented when threads run

I've created the following program which runs two threads with the same thread instance. I've initialised a counter and when each of the thread runs, the counter value should be implemented and at the end it should output in console.
public class MTThread {
static int count = 0;
public static void main(String arg[]){
System.out.println("Main started");
MTThreadInner in1= new MTThreadInner(1,count);
MTThreadInner in2= new MTThreadInner(2,count);
in1.start();
in2.start();
while (true) {
try {
in1.join();
in2.join();
break;
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Main finished, count = :"+ count);
}}
class MTThreadInner extends Thread {
int num; int counter;
MTThreadInner(int i,int z) {
counter=z;
num = i;
}
public void run(){
// TODO Auto-generated constructor stub
yield();
System.out.println("This ran Thread "+ num);
counter=counter+1;
}
}
However the output always shows count as "0":
Main started
This ran Thread 1
This ran Thread 2
Main finished, count = :0
The output should be count = 0 as you don't change this variable anywhere.
What you do is copy this variable to another field in MTThreadInner.counter where each thread changes it's own copy to 1 but this is an entirely unrelated variable.
What you might have expected to do is to increment a shared, thread safe variable. To do this I suggest making count an AtomicInteger
static AtomicInteger count = new AtomicInteger(0);
This way you can copy the reference to the same shared, thread safe object and when you call counter.incrementAndGet() in each thread it will increment this object.
I have created the following program which runs two threads with the same thread instance.
No, you have created a program that runs two threads via different instances of the same Thread subclass.
The counter value should be implemented and at the at end it should output in console.
Each instance of your Thread subclass has a private counter variable, which I'm sure those threads do update (but how could you tell?). That's unrelated to the static variable MTThread.count, which is what you print at the end.

Categories

Resources