How to use multi-threaded wait and notify protocols

Specifically, someone can tell me what's wrong with this code It should start the thread, so it should print "input thread..." five times and wait until notifyall() is called However, it randomly prints "enter..." and "finish..." and is still waiting for others

public class ThreadTest implements Runnable {
    private int num;
    private static Object obj = new Object();
    ThreadTest(int n) {
        num=n;
    }
    @Override
    public void run() {
        synchronized (obj) {
            try {
                System.out.println("Entering thread "+num);
                obj.wait();
                System.out.println("Done Thread "+num);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   
        }   
    }   

    public static void main(String[] args) {
        Runnable tc;
        Thread t;
        for(int i=0;i<5;i++) {
            tc = new ThreadTest(i);
            t = new Thread(tc);
            t.start();
        }
        synchronized (obj) {
            obj.notifyAll();
        }
    }
}

Solution

You didn't make any obvious errors on the method call, but you have a race condition

Although in an ideal world, the main thread will reach its synchronized block after all worker threads arrive at the wait () call, there is no guarantee (you explicitly tell the virtual machine that you don't want the threads to execute in order and make threads with the main thread) It may happen (for example, if you have only one core) that the thread scheduler decides to block all worker threads immediately and they begin to allow the main thread to continue The worker thread may be switched out of context due to a cache miss It may be that a worker thread blocks I / O (print statement) and the main thread switches in its position

Therefore, if the main thread tries to reach the synchronization block before all worker threads reach the wait () call, those worker threads that have not yet reached the wait () call will not run as expected Because the current settings do not allow you to control this operation, you must add explicit processing for this You can add a variable that will be added when each worker thread reaches wait() and the main thread does not call notifyall() until this variable reaches 5, or you can use the main thread loop and call notifyall() repeatedly So that worker threads can be published in multiple groups

Take a look at Java util. Concurrent package - there are several lock classes that provide more powerful functions than basic synchronous locks - as always, Java can save you from reinventing the wheel Countdown latch seems particularly relevant

In short, concurrency is difficult You must design to ensure that when the thread executes in an order you don't want, everything is still valid and the order you want

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>