ReentrantLock
1.什么是可重入锁?
即一个线程持有某个对象的锁时,再次去获取这个对象的锁可以成功的。
ReentrantLock是个典型的独占模式AQS,同步状态为0时表示空闲。当有线程获取到空闲的同步状态时,它会将同步状态加1,将同步状态改为非空闲,于是其他线程挂起等待。在修改同步状态的同时,并记录下自己的线程,作为后续重入的依据,即一个线程持有某个对象的锁时,再次去获取这个对象的锁是可以成功的。
2.ReentrantLock的特点
ReentrantLock锁相对于Synchronized锁的高级功能,
- 等待可中断:指当前持有所得线程长期不释放锁的时候,等待的线程可以选择放弃等待,改为处理其他事情。
将lockInterruptibly() 放到代码块中,调用interrupt方法进行中断时,lockInterruptibly()会立即响应。
@ReservedStackAccess
final void lockInterruptibly() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!initialTryLock())
acquireInterruptibly(1);
}
- 公平锁:指多个线程在等待同一锁时,当锁可用时,必须按照申请锁的时间顺序来依次获取锁。
- 锁绑定多个条件:相对于synchronized 的object.notify() , object.notifyAll() 只能随机唤醒一个,或者全部唤醒。
ReentrantLock唤醒线程时可以有选择的唤醒。
public void threadDemo2() {
Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
lock.lock();
for (int i = 'A'; i < 'K'; i++) {
while (state != 1) {
try {
c1.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print((char) i + " ");
state = 2;
c2.signal();
}
lock.