原理
wait¬ify¬ifyAll都是java的native的方法。
synchronized代码块通过javap生成的字节码中包含 ** monitorenter ** 和 ** monitorexit **指令。使用这三个API的时候,外面必须调用在synchronized中。
表示线程执行lock.wait()方法时,必须持有该lock对象的monitor,如果wait方法在synchronized代码中执行,该线程很显然已经持有了该对象的monitor。wait方法会将当前线程放入wait set,等待被唤醒,并放弃lock对象上的所有同步声明,意味着线程释放锁。
-
notify方法会选择wait set中任意一个线程进行唤醒;
-
notifyAll方法的注释:notifyAll方法会唤醒monitor的wait set中所有线程。
注意事项
如果先notify/notifyAll,再wait,后面的线程将永远等不到唤起。要在代码中坚决避免。
public static void main(String[] args) {
Object o = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
synchronized (o){
System.out.println("t1 notify");
o.notifyAll();
System.out.println("t1 after notify");
}
}catch (Exception ex){
ex.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
synchronized (o){
System.out.println("t2 wait");
o.wait();
System.out.println("t2 after wait");
}
}catch (Exception ex){
ex.printStackTrace();
}
}
});
t1.start();
t2.start();
}