Java锁之重入锁(Reentrantlock)原理,公平锁与非公平锁

Posted 川雨淅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java锁之重入锁(Reentrantlock)原理,公平锁与非公平锁相关的知识,希望对你有一定的参考价值。

1、特点:

已获取锁的线程再次请求锁,可以直接获取。

2、实现:

自定义内部类 Sync,继承 AbstarctQueuedSynchronizer :

2.1、获取锁:lock() 

a、公平锁:

acquire(1)

b、非公平锁:

if (compareAndSetState(0, 1))

        //CAS,当前 state 为0,当前线程占有锁:
  setExclusiveOwnerThread(Thread.currentThread());
else acquire(1);

b.1 AbstarctQueuedSynchronizer acquire(int acquires)

然后是 acquire(1) ——>调用父类 AbstarctQueuedSynchronizer acquire(int acquires)

public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
         selfInterrupt();
}

即如果未获取锁,将请求锁线程加入等待双向队列尾部。然后给当前线程发出中断命令。

Node.EXCLUSIVE = null,

addWaiter(Node node) 将 null 加入等待队列尾部,双向队列。

acquireQueued() 时候再次tryAcquire(arg)

b.2 ReetrantLock tryAcquire(int acquires) 

ReetrantLock 继承 自AbstarctQueuedSynchronizer  的 tryAcquire(int acquires) 如下(使用的 <模板模式>):

根据当前 state 判断当前线程可否获取锁,tryAcquire(int acquires):

如果没有线程持有当前锁:if  0 == getState():

公平锁:CAS将 state 设置为当前占有次数,则将队列中第一个线程唤醒,使其占有锁。

非公平锁:CAS将 state 设置为当前占有次数,直接使当前线程占有锁。

 

如果当前线程持有锁:else if current == getExclusiveOwnerThread(),则将其持有状态值加上aquires。

2.2、释放锁:unlock() ——>AbstarctQueuedSynchronizer   release(1) ——> sync.tryRelease(1)

state = getState -1

若当前线程非持有锁线程,抛异常;

state == 0,当前持有锁线程置空;

否则,setState(state)。

 







以上是关于Java锁之重入锁(Reentrantlock)原理,公平锁与非公平锁的主要内容,如果未能解决你的问题,请参考以下文章

并发编程-AQS同步组件之重入锁ReentrantLock 读写锁ReentrantReadWriteLockCondition

ReentrantLock 重入锁(下)

Java并发-- ReentrantLock 可重入锁实现原理1 - 获取锁

JAVA多线程重入锁ReentrantLock应用

Java 重入锁 ReentrantLock 原理分析

Java并发:重入锁 ReentrantLock