ReentrantLock&AQS
2020-08-14 14:18:55 66 举报
ReetrantLock
作者其他创作
大纲/内容
if (p == head && tryAcquire(arg))
进行CAS操作尝试加锁
否
入队
成功
current == getExclusiveOwnerThread()
是
ReentrantLock.unLock()
setState(c)
FairSync.lock()
唤醒线程
与公平锁一样,入队
free = true;setExclusiveOwnerThread(null);
将持有锁次数+1(可重入锁)
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; }
setState(c + 1);
c == 0
c==0
线程是否处于中断状态
创建一个值含当前线程的Node结点
先尝试加锁,加锁失败再进行入队
ReentrantLock .lock()
//判断前驱结点是信号量是否为-1 int ws = pred.waitStatus; if (ws == Node.SIGNAL)
ReentrantLock LOCK = new ReentrantLock(false);//非公平锁
如果前驱结点为头结点,则尝试获取锁
//将当前结点设为头结点,以便下个结点获取锁setHead(node);
加锁失败
剔除该结点,直到找到正常的前驱结点node.prev = pred = pred.prev;
Thread.interrupted();
结束
信号量为-1,可安全阻塞
获取解锁之后的状态
int c = getState() - releases;
如果下一个节点为空或者无效,则从尾部开始往前找到离头结点最近的有效节点
FairSync.tryAcquire(1)
Node h = head; if (h != null && h.waitStatus != 0)
当前无线程占用锁
加锁成功
NonFairSync.tryAcquire(1)
unparkSuccessor(h)
parkAndCheckInterrupt()
为0表示解锁完毕
已用线程正在持有锁
addWaiter(Node.EXCLUSIVE)
尝试获取锁
被唤醒
解锁
持有锁的线程是否为当前线程
将信号量重置为0
ReentrantLock LOCK = new ReentrantLock(true);//公平锁
AQS.release(1)
尝试获取锁获取锁之后将线程设置为中断状态
//获取当前状态int c = getState()
前驱结点不是头结点,或者再次尝试加锁依旧失败
//设置占用线程为当前线程setExclusiveOwnerThread(current)
LockSupport.park(this); return Thread.interrupted();
//创建一个值为null的头结点enq();
AQS.acquire(1)
队列tail是否为null
判断是否需要阻塞线程
h!=null 表示有线程正在等待唤醒,h.waitStatus!=0表示线程已准备好被唤醒
此时为公平锁,对列中有其他线程,直接入队
hasQueuedPredecessors()
无判断队列中是否有线程排队操作,直接尝试加锁
还有锁没解完(可重入锁)free=false
大于0表示该结点已无效信号量为CANCELLED
判断状态
NonfairSync.lock()
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;
加锁
free==true
//Node 状态与信号量 static final Node SHARED = new Node(); static final Node EXCLUSIVE = null; static final int CANCELLED = 1; static final int SIGNAL = -1; static final int CONDITION = -2; static final int PROPAGATE = -3;
重试
失败
ReentrantLock .tryRelease(arg)
将新结点添加至结点末尾,并将tail指向新结点,返回新node结点
ReentrantLock LOCK = new ReentrantLock();//解锁时公平锁与非公平锁逻辑相同
//信号量是否大于0ws>0
//获取node结点的前驱结点Node p = node.predecessor();
此时线程已阻塞,等待唤醒
锁已解完,设置占用线程为null
if (s != null) LockSupport.unpark(s.thread);
队列中是否有其他线程正在等待加锁
CAS操作失败,锁已被其他线程抢占,进行入队操作
0 条评论
下一页