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();
}
}