Lock&Condition
Java SDK的Lock&Condition是并发包工具。和synchronized类似,都是基于管程的实现。Lock实现了管程的互斥,Condition实现了同步。
既然java中已经存在了synchronized,为什么还要实现Lock&Condition?
除了我们知道的,java的1.5版本和java的1.6版本,synchronized和lock之间的性能竞争外。最重要的一点是,Lock在相对于synchronized的隐式获取锁lock()外,增加了支持中断响应,非阻塞,超时获取锁,破坏了不可抢占的死锁条件,从而有机会,提高了程序的安全性和健壮性。
公平锁和非公平锁
- 公平锁:在管程获取不到资源时,将线程放入阻塞队列中,选择阻塞时间唤醒长的阻塞线程。
Lock fairLock = new ReentrantLock(true);
- 非公平锁:在阻塞队列中随机唤醒线程。(一般默认都是非公平的)
可重入锁/非可重入锁
场景:当线程持有锁a时,重复获得锁a时
- 可重入锁:线程可以再次加锁a成功
- 非可重入锁:线程将会阻塞
condition
在java内置管程只有一个条件变量,而Lock&Condition中,则可以实现多个条件变量。通过Condition中await(),signal(),signalAll()的行为使线程阻塞/唤醒。与wait(),notify(),notifyAll()相同语义,但不可以混乱使用。
通过Condition实现简陋的限流器,如下。
public class ConditionTest {
final int size = 10;
private int count = 0;
final Lock lock = new ReentrantLock();
//条件变量(不能为满)
final Condition notFull = lock.newCondition();
//条件变量(不能为空)
final Condition notEmpty = lock.newCondition();
public void get() {
lock.lock();
try {
//同步获取
while (count <= 0)
{
notEmpty.await();
}
count--;
notFull.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void set()
{
lock.lock();
try{
while (count >= size)
{
notFull.await();
}
count++;
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
}
}