wait() 与 notify/notifyAll() 是Object类的方法,在执行两个方法时,要先获得锁。
当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。
当执行notify/notifyAll方法时,会唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。
从这里可以看出,notify/notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中代码后,再释放。所以在实际编程中,我们应该尽量在线程调用notify/notifyAll()后,立即退出临界区。即不要在notify/notifyAll()后面再写一些耗时的代码。
通过ReentrantLock我们可以很方便的进行显式的锁操作,即获取锁和释放锁,对于同一个对象锁而言,统一时刻只可能有一个线程拿到了这个锁,此时其他线程通过lock.lock()来获取对象锁时都会被阻塞,直到这个线程通过lock.unlock()操作释放这个锁后,其他线程才能拿到这个锁。
package com.concurrent.syn;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
-
@author riemann
-
@date 2019/08/03 0:12
*/
public class PrintLetter_Lock {
private static Lock lock = new ReentrantLock();// 通过JDK5中的Lock锁来保证线程的访问的互斥
private static int state = 0;//通过state的值来确定是否打印
static class ThreadA extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; ) {
try {
lock.lock();
while (state % 3 == 0) {// 多线程并发,不能用if,必须用循环测试等待条件,避免虚假唤醒
System.out.print(“a”);
state++;
i++;
}
} finally {
lock.unlock();// unlock()操作必须放在finally块中
}
}
}
}
static class ThreadB extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; ) {
try {
lock.lock();
while (state % 3 == 1) {// 多线程并发,不能用if,必须用循环测试等待条件,避免虚假唤醒
System.out.print(“b”);
state++;
i++;
}
} finally {
lock.unlock();