1.ReetrantLock —— 实现原理:
实际组成:
获取到锁的:首先将status置为1,再一次获取这个锁的时候,在这个status上进行++的操作。
没有获取到锁的:有一个双向链表,进来的线程都挂在这个链表的尾部,保持头指针为null
加锁过程:
线程 1,2,3进来,可以选择公平锁和非公平锁的实现方式。
1)首先通过CAS去置位
if 成功则占有锁
标记自身占有锁,把state置为1
else
再去尝试 2)。
2)去获取一个state
if (state ==0)
执行1)
else if(state>0 && 占有的线程是当前线程)
state++;
else
没有占有到锁
3) 将自己放入一个等待的FIFO的队列
if(队列的尾节点==null)
初始化,直接放入尾节点
else(不为空){
将上一个节点的next指向该节点,使该节点成为新的尾节点
if(当多个节点去占有尾节点){
whlie(每个线程放进队列里){
使用CAS去占有尾节点
}
}
}
4 if(当前节点的头结点为Null){
获取锁
if(失败){
waitStatus == SIGNAL;
该线程挂起;
递归去挂起后面的等待节点的线程,都是将每个节点对应的waitStatus置为SIGNAL;
}
}
注意:
AQS的FIFO的等待队列给解决在锁竞争方面的羊群效应问题提供了一个思路:保持一个FIFO队列,队列每个节点只关心其前一个节点的状态,线程唤醒也只唤醒队头等待线程。
参考:
https://blog.csdn.net/yanyan19880509/article/details/52345422
http://www.importnew.com/24006.html
https://blog.csdn.net/jiangjiajian2008/article/details/52226189
网友评论