Java 通过 Lock 和 竞争条件 Condition 实现
2016-12-23 本文已影响69人
专职跑龙套
竞争条件
多个线程共享对某些变量的访问,其最后结果取决于哪个线程偶然在竞争中获胜。
-
condition.await()
:类似于obj.wait()
-
condition.signal()
:类似于obj.notify()
-
condition.signalAll()
:类似于obj.notifyAll()
竞争条件 Condition 对比 obj.wait() obj.notify() 的优势
可以建立不同的多个 Condition,针对不同的竞争条件,例如:
Condition isFullCondition = lock.newCondition();
Condition isEmptyCondition = lock.newCondition();
关于 通过 wait 和 notify 实现生产者消费者模式,可以参考 链接。
利用 Lock 和 竞争条件 Condition 也可以实现生产者消费者模式,代码如下:
public class Condition_Test {
private static final int MAX_CAPACITY = 10;
private static List<Object> goods = new ArrayList<Object>();
private static final Lock lock = new ReentrantLock();
private static final Condition isFullCondition = lock.newCondition();
private static final Condition isEmptyCondition = lock.newCondition();
public static void main(String[] args) {
(new ProducerThread()).start();
(new ConsumerThread()).start();
}
static class ProducerThread extends Thread {
public void run() {
while (true) {
// 每隔 1000 毫秒生产一个商品
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// 获得锁,相当于 synchronized
lock.lock();
// 当前商品满了,生产者等待
if (goods.size() == MAX_CAPACITY) {
try {
System.out.println("Goods full, waiting...");
isEmptyCondition.await();
} catch (Exception e) {
}
}
goods.add(new Object());
System.out.println("Produce goods, total: " + goods.size());
// isFullCondition.signal() 也可以
isFullCondition.signalAll();
// 记住要释放锁
lock.unlock();
}
}
}
static class ConsumerThread extends Thread {
public void run() {
while (true) {
// 每隔 500 毫秒消费一个商品
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
// 获得锁,相当于 synchronized
lock.lock();
// 当前商品空了,消费者等待
if (goods.size() == 0) {
try {
System.out.println("No goods, waiting...");
isFullCondition.await();
} catch (Exception e) {
}
}
goods.remove(0);
System.out.println("Consume goods, total: " + goods.size());
// isEmptyCondition.signal() 也可以
isEmptyCondition.signalAll();
// 记住要释放锁
lock.unlock();
}
}
}
}
Condition 的实现原理
Condition
的内部实现是使用节点链来实现的,每个条件实例对应一个节点链,我们有 isFullCondition
和 isEmptyCondition
两个条件实例,所以会有两个等待节点链。当对应条件被 signal
的时候,就会把等待节点转移到同步队列中,继续竞争锁。