ReentrantLock 有如下特点:
-
可重入 ReentrantLock 和 syncronized 关键字一样,都是可重入锁,不过两者实现原理稍有差 别, RetrantLock 利用 AQS 的的 state 状态来判断资源是否已锁,同一线程重入加锁, state 的状态 +1 ; 同一线程重入解锁, state 状态 -1 (解锁必须为当前独占线程,否则异 常); 当 state 为 0 时解锁成功。
-
需要手动加锁、解锁 synchronized 关键字是自动进行加锁、解锁的,而 ReentrantLock 需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成,来手动加锁、解锁。
-
支持设置锁的超时时间 synchronized 关键字无法设置锁的超时时间,如果一个获得锁的线程内部发生死锁,那 么其他线程就会一直进入阻塞状态,而 ReentrantLock 提供 tryLock 方法,允许设置线 程获取锁的超时时间,如果超时,则跳过,不进行任何操作,避免死锁的发生。
-
支持公平/非公平锁 synchronized 关键字是一种非公平锁,先抢到锁的线程先执行。而 ReentrantLock 的 构造方法中允许设置 true/false 来实现公平、非公平锁,如果设置为 true ,则线程获取 锁要遵循"先来后到"的规则,每次都会构造一个线程 Node ,然后到双向链表的"尾 巴"后面排队,等待前面的 Node 释放锁资源。
-
可中断锁 ReentrantLock 中的 lockInterruptibly() 方法使得线程可以在被阻塞时响应中断,比 如一个线程 t1 通过 lockInterruptibly() 方法获取到一个可重入锁,并执行一个长时间 的任务,另一个线程通过 interrupt() 方法就可以立刻打断 t1 线程的执行,来获取t1持 有的那个可重入锁。而通过 ReentrantLock 的 lock() 方法或者 Synchronized 持有锁 的线程是不会响应其他线程的 interrupt() 方法的,直到该方法主动释放锁之后才会响应 interrupt() 方法。