Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread join() does not wait

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

I have a Thread (ThreadAdd.java) which 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 launch 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 do not understand why most of the time the result is 2 but sometimes it returns 1.

like image 717
damien marchand Avatar asked Feb 21 '15 12:02

damien marchand


People also ask

Does thread join wait?

join() Method. Waits for this thread to die. When we invoke the join() method on a thread, the calling thread goes into a waiting state.

What does join () method of thread do?

Join is a synchronization method that blocks the calling thread (that is, the thread that calls the method) until the thread whose Join method is called has completed. Use this method to ensure that a thread has been terminated. The caller will block indefinitely if the thread does not terminate.

Does join method accept a timeout?

Both wait() and join() can be interrupted by calling interrupt() method in Java. Both wait() and join() are a non-static method. Both wait() and join() are overloaded in Java. wait() and join() which without timeout as well as accepts a timeout parameter.

Is wait () in thread class?

wait() method is a part of java. lang. Object class. When wait() method is called, the calling thread stops its execution until notify() or notifyAll() method is invoked by some other Thread.


2 Answers

The reason why you sometimes see 1 is not because join() fails to wait for the thread to finish, but because both threads tried to modify the value concurrently. When this happens, you may see unexpected results: for example, when both threads try to increment count which is zero, they both could read zero, then add 1 to it, and store the result. Both of them will store the same exact result, i.e. 1, so that's what you are going to see no matter how long you wait.

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();
}
like image 100
Sergey Kalinichenko Avatar answered Nov 15 '22 09:11

Sergey Kalinichenko


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

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

like image 35
E_net4 stands with Ukraine Avatar answered Nov 15 '22 10:11

E_net4 stands with Ukraine