ReentrantLock获取锁及释放锁流程

ReentrantLock特性:可重入、排它锁

内部使用AQS(AbstractQueuedSynchronizer)实现,主要技术:CAS、park/unpark

主要使用AQS的两个成员变量来实现可重入排它锁。

可重入:AQS.state用于记录进入锁的次数。

排它锁:AQS.exclusiveOwnerThread用户当前占有锁的线程。

一个线程获取锁时,调用ReentrantLock.lock(),如果没有别的线程竞争锁、或者锁已经被当前线程占有,可以尝试直接占有锁,

如果成功,则继续执行同步代码块;

如果失败,说明有别的线程竞争,则需要进行排队等候其他已经占用锁的线程释放锁。

占有锁的线程释放锁时,需要检查是否已经彻底丢弃锁占有(因为如果线程重入占用锁N次,那么就需要有N次释放锁与之对应),如果已经彻底丢弃锁占有,那么需要检查是否别的线程在等待,如果有,则需要唤醒等待队列中的第一个未被取消的线程。

Reentrant有两种实现:公平锁、非公平锁,区别在于:非公平锁在尝试获取锁时,可以不管是否有等待队列,只要当前锁未被占用,就可以直接尝试占有锁。

当前锁未被占用,有两种情况:

(1)没有线程等待锁

(2)占有锁的线程刚刚释放锁,且还没来得及唤醒等待队列的线程

对于第2种情况,省去了当前获取锁的线程的睡眠和唤醒操作,可以提高整体效率。

ReentrantLock获取锁及释放锁流程_第1张图片

你可能感兴趣的:(Java)