Wait()/ notify()同步

rei*_*ley 10 java multithreading synchronization

我正在尝试检查java中wait/notify的工作原理.

码:

public class Tester {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
        synchronized (t) {
            try {
                System.out.println("wating for t to complete");
                t.wait();
                System.out.println("wait over");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("entering run method");
        synchronized (this) {
            System.out.println("entering syncronised block");
            notify();
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("leaving syncronized block");
        }
        System.out.println("leaving run method");
    }
}
Run Code Online (Sandbox Code Playgroud)

输出返回

wating for t to complete
entering run method
entering syncronised block
//sleep called
leaving syncronized block
leaving run method
wait over
Run Code Online (Sandbox Code Playgroud)

我期待当执行notify()时,等待将结束System.out.println("wait over");并将被打印.但它似乎只有在t完成它时才会打印出来run().

Mad*_*mer 11

对象监视器锁需要执行相同锁的单个引用...

在你的榜样,你是waiting对的一个实例Thread,但使用notifyRunnable.相反,您应该使用单个公共锁定对象...例如

public class Tester {

    public static final Object LOCK = new Object();

    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
        synchronized (LOCK) {
            try {
                System.out.println("wating for t to complete");
                LOCK.wait();
                System.out.println("wait over");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyRunnable implements Runnable {

        public void run() {
            System.out.println("entering run method");
            synchronized (LOCK) {
                System.out.println("entering syncronised block");
                LOCK.notify();
                try {
                    Thread.currentThread().sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("leaving syncronized block");
            }
            System.out.println("leaving run method");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出...

wating for t to complete
entering run method
entering syncronised block
leaving syncronized block
wait over
leaving run method
Run Code Online (Sandbox Code Playgroud)

wait over并且leaving run method可以根据线程调度来改变位置.

你可以尝试把睡眠放在一边synchronized.这将释放监视器锁定,允许该wait部分继续运行(因为它在锁定释放之前无法启动)

    public static class MyRunnable implements Runnable {

        public void run() {
            System.out.println("entering run method");
            synchronized (LOCK) {
                System.out.println("entering syncronised block");
                LOCK.notify();
                System.out.println("leaving syncronized block");
            }
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("leaving run method");
        }
    }
Run Code Online (Sandbox Code Playgroud)


Pyr*_*nja 5

回答更新的代码:

来自Thread.sleep() javadoc:

导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性.该线程不会失去任何监视器的所有权.

如果在同步块内部调用Thread.sleep,则其他线程将无法进入同步块.在同步块中,您永远不应该耗费时间来避免这种情况.