synchronized中也有条件变量,当条件不满足时进入WaitSet等待。
ReentrantLock的条件变量比Synchronized强大之处在于它支持多个条件变量。
await和signal方法
多条件变量的使用流程
1.await需要获得锁。
2.await执行后会释放锁,进入ConditionObject等待。
3.await被线程唤醒、或者打断、或者超时会重新竞争lock锁。
4.竞争lock成功后,从await后继续执行。
@Slf4j
public class ReentrantLockBean {private static ReentrantLock reentrantLock = new ReentrantLock();private static boolean hasCigarette = false;private static boolean hasMeal = false;//条件一,等烟的房间private static Condition waitCigaretteRoom = reentrantLock.newCondition();//条件二,等餐的房间private static Condition waitMealRoom = reentrantLock.newCondition();public static void main(String[] args) {new Thread(()->{reentrantLock.lock();try {log.info("有烟没?{}", hasCigarette);while(!hasCigarette) { // 没有烟log.info("没有烟歇会....");try {//获得锁后进行等待,进入条件一,等烟的房间waitCigaretteRoom.await();} catch (InterruptedException e) {e.printStackTrace();}}log.info("开始干活.....");} finally {reentrantLock.unlock();}}, "t1").start();new Thread(() -> {reentrantLock.lock();try {log.info("外卖到了没?{}", hasMeal);while (!hasMeal) {//没有送到log.info("外卖没有到...");try {//获得锁后进行等待,进入条件二,等餐的房间waitMealRoom.await();} catch (InterruptedException e) {e.printStackTrace();}}log.info("开始工作.....");}finally {reentrantLock.unlock();}}, "t2").start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {reentrantLock.lock();try {log.info("烟来了...");hasCigarette = true;//唤醒等烟的条件变量waitCigaretteRoom.signal();}finally {reentrantLock.unlock();}}, "t3").start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {reentrantLock.lock();try {log.info("餐来了...");hasMeal = true;//唤醒等餐的条件变量waitMealRoom.signal();}finally {reentrantLock.unlock();}}, "t4").start();}
}