一、简介
上一篇我们介绍了使用传统的synchronized结合wait()/notifyAll()线程通信机制实现了生产者消费者案例,并且介绍了多线程交互中常见的虚假唤醒现象。我们都知道,Lock同步锁其实可以代替synchronized完成同步功能,并且使用起来还没有那么复杂,本文将介绍如何使用Lock实现生产者消费者案例。
下表是synchronized和Lock实现线程通信方法的区别:
synchronized |
Lock |
wait() |
await() |
notifyAll() |
signalAll() |
Lock结合Condition可以替代synchronized实现同步功能,JDK官网介绍如下:
并且官网也给了Condition的使用示例:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
Condition可以更精确地控制到各个线程的执行,相当于各个线程的某个条件。
二、案例
public class T06_ProducerAndConsumer02 {
public static void main(String[] args) {
AirCondition2 airCondition = new AirCondition2();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
airCondition.incr();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
airCondition.decr();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
airCondition.incr();
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
airCondition.decr();
}
}, "D").start();
}
}
class AirCondition2 {
private int number = 0;
//可重入锁
private Lock lock = new ReentrantLock();
//创建Condition条件
private Condition condition = lock.newCondition();
public void incr() {
lock.lock();
try {
while (number != 0) {
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "->number:" + number);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decr() {
lock.lock();
try {
while (number == 0) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number--;
System.out.println(Thread.currentThread().getName() + "->number:" + number);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
运行结果:
A->number:1
B->number:0
C->number:1
D->number:0
A->number:1
B->number:0
A->number:1
B->number:0
C->number:1
D->number:0
A->number:1
B->number:0
A->number:1
D->number:0
C->number:1
B->number:0
A->number:1
B->number:0
A->number:1
D->number:0
C->number:1
B->number:0
A->number:1
B->number:0
A->number:1
D->number:0
C->number:1
B->number:0
A->number:1
D->number:0
C->number:1
B->number:0
C->number:1
D->number:0
C->number:1
D->number:0
C->number:1
D->number:0
C->number:1
D->number:0
通过运行结果可知,使用Condition同样可以进行线程之间的通信,并且Condition方式比synchronized方式要灵活得多,使用起来也比较简单。
来源:CSDN
作者:人丑就该多读书呀
链接:https://blog.csdn.net/Weixiaohuai/article/details/104591862