Thread join () does not wait

I am trying to learn about threads and I do not understand the join() method.

I have a Thread (ThreadAdd.java) that adds 1 to a static int.

 public class ThreadAdd extends Thread{ public static int count; @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException ex) { Logger.getLogger(ThreadAdd.class.getName()).log(Level.SEVERE, null, ex); } ThreadAdd.count++; } } 

In my main method, I start 2 threads:

  public static void main(String[] args) throws InterruptedException { ThreadAdd s1 = new ThreadAdd(); ThreadAdd s2 = new ThreadAdd(); s1.start();s2.start(); s1.join(); s2.join(); System.out.println(ThreadAdd.count); } 

I don’t understand why in most cases the result is 2, but sometimes it returns 1.

+7
java multithreading
source share
5 answers

The reason you sometimes see 1 is not because join() cannot wait for the thread to end, but because both threads tried to change the value at the same time. When this happens, you can see unexpected results: for example, when both threads try to increase the count , which is zero, they can both read zero, then add 1 to it and save the result. Both of them will keep the same exact result, i.e. 1, so you will see no matter how much you expect.

To fix this problem, add synchronized around the increment or use AtomicInteger :

 public static AtomicInteger count = new AtomicInteger(0); @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException ex) { Logger.getLogger(ThreadAdd.class.getName()).log(Level.SEVERE, null, ex); } ThreadAdd.count.incrementAndGet(); } 
+11
source share

Because you do not synchronize the integer increment count . These two threads can alternate with increasing variable.

See http://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html for an explanation. The example in the link is similar to your example, and the solution provided to prevent this stream interference is to use atomic variables like java.util.concurrent.atomic.AtomicInteger .

+4
source share

The join method is not a real problem here. The problem is that your counter is not prepared for interthread synchronization, which may cause each thread to observe a different value in count .

It is highly recommended that you study some of the topics in parallel programming, including how it is handled in Java.

+4
source share

Your count variable is not volatile , and therefore there is no need to check its value every time, and sometimes ordering the instructions causes such errors.

Actually, since count++ is the syntactic sugar for count = count + 1 , even if the volatile variable does not guarantee that you have no problem, since there is a race condition between reading and subsequent writing.

To make such code safe, use AtomicInteger instead.

+2
source share

This has nothing to do with join . The thread that is waiting with join() is your main thread. The other two threads expect nothing. And join does not force them to do anything differently.

And, as the other answers said, two threads are simultaneously written to the same variable, and therefore you get the result that you see.

You might have expected join() delay one of the threads so that it doesn't work at the same time as the other, but not the way it works. The only thread that is delayed is the calling join() object, not the target thread.

+2
source share

All Articles