ReentrantLock笔记

构造方法生成公平与非公平锁
public ReentrantLock( boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}

//上锁

public void lock() {
sync .lock();
}
先看公平锁
final void lock() {
acquire( 1 );
}
进入 AbstractQueuedSynchronizer的 acquire( 1 )方法
public final void acquire( int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node. EXCLUSIVE ), arg))
selfInterrupt ();
}
先尝试 tryAcquire(arg)回到 ReentrantLock里面
protected final boolean tryAcquire( int acquires) {
final Thread current = Thread. currentThread ();
//获得锁状态
int c = getState();
if (c == 0 ) {
//判断等待队列里是否有值有值则结束返回false
if (!hasQueuedPredecessors() &&
// 否则尝试修改state
compareAndSetState( 0 , acquires)) {
// 成功了就设置当前线程为占用线程
setExclusiveOwnerThread(current);
return true ;
}
}
//判断是否重入
else if (current == getExclusiveOwnerThread()) {
//增加线程数
int nextc = c + acquires;
if (nextc < 0 )
throw new Error( "Maximum lock count exceeded" );
//修改state的值
setState(nextc);
return true ;
}
return false ;
}

tryAcquire(arg) 在失败后执行 acquireQueued(addWaiter(Node. EXCLUSIVE ), arg)
先看看 addWaiter(Node. EXCLUSIVE )

private Node addWaiter(Node mode) {
//新建节点
Node node = new Node(Thread. currentThread (), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail ;
//如果尾部tail不为空
if (pred != null ) {
node. prev = pred;
//尝试着修改尾部失败了结束,成功了返回node
if (compareAndSetTail(pred, node)) {
pred. next = node;
return node;
}
}
//自旋修改
enq(node);
return node;
}
进入 enq()

private Node enq( final Node node) {
for (;;) {
Node t = tail ;
if (t == null ) { // Must initialize
//尾巴为空初始化,头等于尾,这边新建一个空的node来作为头,具体原因在 acquireQueued()
if (compareAndSetHead( new Node()))
tail = head ;
} else {
node. prev = t;
//设置tail为node失败自旋
if (compareAndSetTail(t, node)) {
t. next = node;
return t;
}
}
}
}

返回之后再进入 acquireQueued( final Node node, int arg)
final boolean acquireQueued( final Node node, int arg) {
boolean failed = true ;
try {
boolean interrupted = false ;
for (;;) {
//这个 node.predecessor里面的prev为空会报错,就是要新建一个空头
final Node p = node.predecessor();
//当前线程前面一个判断是不是头,是的话 tryAcquire抢占用
if (p == head && tryAcquire(arg)) {
setHead(node);
p. next = null ; // help GC
failed = false ;
return interrupted;
}
//判断要不要wait一下
if ( shouldParkAfterFailedAcquire (p, node) &&
parkAndCheckInterrupt())
interrupted = true ;
}
} finally {
if (failed)
//取消
cancelAcquire(node);
}
}
查看下 shouldParkAfterFailedAcquire

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred. waitStatus ;
if (ws == Node. SIGNAL )
//这个节点已经设置了请求释放信号的状态,这样它就可以安全地停车了
return true ;
if (ws > 0 ) {
//前面有取消的,就循环获得正常的
do {
node. prev = pred = pred. prev ;
} while (pred. waitStatus > 0 );
pred. next = node;
} else {
//waitStatus必须为0或传播。表明我们需要信号,但不要停车。访客需要重试,以确保在停车前不能获得。
compareAndSetWaitStatus (pred, ws, Node. SIGNAL );
}
//返回重试,有可能已经释放了锁
return false ;
}
看一下 cancelAcquire(node)

private void cancelAcquire(Node node) {
// Ignore if node doesn't exist
if (node == null )
return ;

node. thread = null ;

// 跳过取消前任
Node pred = node. prev ;
while (pred. waitStatus > 0 )
node. prev = pred = pred. prev ;

// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
Node predNext = pred. next ;
//当前节点状态设为 CANCELLED
node. waitStatus = Node. CANCELLED ;

// 如果我们是尾巴,那就移走我们自己 .把刚才正常的作为尾巴
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext (pred, predNext, null );
} else {
//如果后续需要信号,试着设置pred的下一个链接,这样它就会得到一个。否则,唤醒它以传播。
//把取消的节点的下个设置到刚才正常的节点上面.
//如果跑到这边之后前面的节点也取消了,cas节点连接到取消的节点就继续循环
int ws;
if (pred != head &&
((ws = pred. waitStatus ) == Node. SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus (pred, ws, Node. SIGNAL ))) &&
pred. thread != null ) {
Node next = node. next ;
if (next != null && next. waitStatus <= 0 )
compareAndSetNext (pred, predNext, next);
} else {
//唤醒下一个线程
unparkSuccessor(node);
}

node. next = node; // help GC
}
}

解锁
public void unlock() {
sync .release( 1 );
}


private void unparkSuccessor(Node node) {
int ws = node. waitStatus ;
if (ws < 0 )
compareAndSetWaitStatus (node, ws, 0 );
//找出下一个Node解锁
Node s = node. next ;
if (s == null || s. waitStatus > 0 ) {
s = null ;
for (Node t = tail ; t != null && t != node; t = t. prev )
if (t. waitStatus <= 0 )
s = t;
}
if (s != null )
LockSupport. unpark (s. thread );
}

非公平锁
//非公平锁就是这边会先去cas枪战一下状态
final void lock() {
if (compareAndSetState( 0 , 1 ))
setExclusiveOwnerThread(Thread. currentThread ());
else
acquire( 1 );
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值