ReentrantLock
ReentrantLock(轻量级锁)也可以叫对象锁,可重入锁,互斥锁。synchronized重量级锁,JDK前期的版本lock比synchronized更快,在JDK1.5之后synchronized引入了偏向锁,轻量级锁和重量级锁。以致两种锁性能旗鼓相当,看个人喜欢,本文主要介绍一下lock和tryLock的区别。
Lock VS TryLock
1 public void lock() {
2 sync.lock();
3 }
4
5 public void lockInterruptibly() throws InterruptedException {
6 sync.acquireInterruptibly(1);
7 }
8
9
10
11 public boolean tryLock() {
12 return sync.nonfairTryAcquire(1);
13 }
14
15
16 public boolean tryLock(long timeout, TimeUnit unit)
17 throws InterruptedException {
18 return sync.tryAcquireNanos(1, unit.toNanos(timeout));
19 }
举一个例子如下:
假如线程A
和线程B
使用同一个锁LOCK
,此时线程A首先获取到锁LOCK.lock()
,并且始终持有不释放。如果此时B要去获取锁,有四种方式:
-
LOCK.lock()
: 此方式会始终处于等待中,即使调用B.interrupt()
也不能中断(本质是排队时的LockSurport.park()被中断了,发现以后不抛出异常),除非线程A调用LOCK.unlock()
释放锁。 -
LOCK.lockInterruptibly()
: 此方式会等待,但当调用B.interrupt()
会被中断等待(本质是排队时的LockSurport.park()被中断了,发现以后抛出异常),并抛出InterruptedException
异常,否则会与lock()
一样始终处于等待中,直到线程A释放锁。 -
LOCK.tryLock()
: 该处不会等待,获取不到锁并直接返回false,去执行下面的逻辑。 -
LOCK.tryLock(10, TimeUnit.SECONDS)
:该处会在10秒时间内处于等待中(该方法也会参与队列的排队),但当调用B.interrupt()
会被中断等待,并抛出InterruptedException
。10秒时间内如果线程A释放锁,会获取到锁并返回true,否则10秒过后会获取不到锁并返回false,去执行下面的逻辑。
关键代码
lock对于中断的处理
lockInterruptibly
对于中断的处理
tryLock
对于中断的处理(根本不参与排队,但是更新state标识,所以也得释放锁)
tryLock(10, TimeUnit.SECONDS)
对于中断的处理
Lock和TryLock的区别
1: lock拿不到锁会一直等待。tryLock是去尝试,拿不到就返回false,拿到返回true。
2: 两者都需要去调用unlock释放锁