首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

JUC代码浅析[二]——基于AQS的锁ReentrantLock

2012-08-21 
JUC代码浅析[2]——基于AQS的锁ReentrantLockJUC代码浅析[2]——基于AQS的锁ReentrantLock???????? ReentrantL

JUC代码浅析[2]——基于AQS的锁ReentrantLock

JUC代码浅析[2]——基于AQS的锁ReentrantLock

???????? ReentrantLock是使用比较普遍的一个可重入锁,它是互斥的,一个锁只能被一个线程占有。它的方法基本都是委托给继承AQS的Sync实现的。其中Sync有两种实现,公平和非公平。Sync使用state(通过AQS暴露的getState和setState方法)保存线程的获取次数。总的策略为state次数为0时可以获得锁。大于0时,如果当前线程已经拥有该锁则可再次获得,否则进入AQS的调度逻辑(<JUC代码浅析——同步器AQS>中介绍)。下面为非公平ReentrantLock的NonfairSync实现,

??????? final void lock() {

??????????? if (compareAndSetState(0,1))

???????????????setExclusiveOwnerThread(Thread.currentThread());

??????????? else

?? ?????????????acquire(1);

??????? }

如果state次数为0的话,获得成功并设置当前线程为锁的拥有者。

否则进入AQS调度,acquire(1)方法使用tryAcquire尝试获得,这里重载的tryAcquire调用的是nonfairTryAcquire方法

??????? final boolean nonfairTryAcquire(int acquires) {

??????????? final Thread current = Thread.currentThread();

??????????? int c = getState();

?????????? //如果当前重进入数为0,有机会取得锁

??????????? if (c == 0) {

?????????? //获得成功并设置当前线程为锁的拥有者

??????????????? if (compareAndSetState(0, acquires)) {

???????????????????setExclusiveOwnerThread(current);

? ??????????????????return true;

??????????????? }

??????????? }

?????? //如果当前线程已经拥有该锁则可再次获得

??????????? else if (current == getExclusiveOwnerThread()) {

??????????????? int nextc = c + acquires;

??????????????? if (nextc < 0) // overflow

??????????????????? throw new Error("Maximumlock count exceeded");

??????????????? setState(nextc);

??????????????? return true;

??????????? }

?????? //都不满足,则进入AQS队列等待调度

??????????? return false;

??????? }

?

公平ReentrantLock的FairSync实现

protected final boolean tryAcquire(int acquires) {

??????????? final Thread current = Thread.currentThread();

??????????? int c = getState();

?????? //如果当前重进入数为0,有机会取得锁

??????????? if (c == 0) {

?????????? //如果当前线程是第一个等待者,获得成功并设置当前线程为锁的拥有者

??????????????? if (isFirst(current) &&

??????????????????? compareAndSetState(0,acquires)) {

???????????????????setExclusiveOwnerThread(current);

??????????????????? return true;

??????????????? }

??????????? }

?????? //如果当前线程已经拥有该锁则可再次获得

??????????? else if (current == getExclusiveOwnerThread()) {

??????????????? int nextc = c + acquires;

??????????????? if (nextc < 0)

??????????????????? throw new Error("Maximumlock count exceeded");

??????????????? setState(nextc);

??????????????? return true;

??????????? }

?????? //都不满足,则进入AQS队列等待调度

??????????? return false;

??????? }

?

?????? fairSync和NonfairSync的tryRelease方法是同一个,比较简单,就是改变一下state次数,如果需要的话把拥有者线程置为null

??????? protected final boolean tryRelease(int releases) {

??????????? int c = getState() - releases;

??????????? if (Thread.currentThread() !=getExclusiveOwnerThread())

??????????????? throw new IllegalMonitorStateException();

??????????? boolean free = false;

??????????? if (c == 0) {

??????????????? free = true;

??????????????? setExclusiveOwnerThread(null);

?????? ?????}

??????????? setState(c);

??????????? return free;

??????? }

?

?????? 公平和非公平的区别就在于,尝试进入的时候需要判断当前线程是否是队列的第一个,是第一个才能进入。这样AQS在调度的时候就会阻塞掉很多线程,性能差别就比较大。ReentrantLock只支持互斥模式,没有共享模式

?

热点排行