synchronized(lock)中确定了,当前线程执行这段同步代码块,必须获取lock的对象锁(也就是判断lock对象的加锁计数器的值是否为零,为零则获取并将加锁计数器的值加1,不为零等待)。
在代码块中执行lock.wait()方法,该线程放弃lock对象锁(也就是lock维护的加锁计数器的值减1),等待其他线程执行notifyAll()或者notify()方法可能将它唤醒…,还有很多不细说了。
notify()或notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或 notifAll()的线程释放锁之后,等待线程才有机会从wait()返回。
直接执行wait(),会报异常。如果这一同步代码所在方法是实例方法那就是实例的this.wait()方法 ,如果是类方法,那就执行Class对象的wait()方法。 很明显,该线程并没有获取到这两个对象的对象锁,而执行wait()方法的前提就是当前线程获取了对象的对象锁,所以会报异常。
代码示例:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class WaitNotify {
static boolean flag = true;
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread waitThread = new Thread(new Wait(),"WaitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(1);
Thread notifyThread = new Thread(new Notify(),"NotifyThread");
notifyThread.start();
}
static class Wait implements Runnable{
public void run(){
// 加锁,拥有lock的Monitor
synchronized (lock){
// 当条件不满足时,继续wait,同时释放了lock的锁
while(flag){
try {
System.out.println(String.format(Thread.currentThread() + " flag is true. wait@ " + new SimpleDateFormat("HH:mm:ss").format(new Date())));
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread() + " flag is false. running@ "+new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
static class Notify implements Runnable{
@Override
public void run() {
// 加锁,拥有lock的Monitor
synchronized (lock){
// 获取lock的锁,然后进行通知,通知时不会释放锁,
// 直到当前线程释放lock后,WaitThread 才能从wait方法中返回
System.out.println(Thread.currentThread() + " hold lock. notify@ "+new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
flag = false;
}
synchronized (lock){
System.out.println(Thread.currentThread() + "hold lock again. sleep@ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
Thread.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}