Node node = myNode.get();
node.locked = true;
Node pred = tail.getAndSet(node);
myPred.set(pred);
while (pred.locked){}
}
public void unLock(){
Node node = myNode.get();
node.locked=false;
myNode.set(myPred.get());
}
static class Node {
volatile boolean locked = false;
}
}
### []( )MCS锁
MSC与CLH最大的不同并不是链表是显示还是隐式,而是线程自旋的规则不同:CLH是在前趋结点的locked域上自旋等待,而MCS是在自己的结点的locked域上自旋等待。正因为如此,它解决了**CLH在NUMA系统架构中获取locked域状态内存过远的问题 。**
#### []( )MCS锁具体实现规则:
* a. 队列初始化时没有结点,tail=null
* b. 线程A想要获取锁,将自己置于队尾,由于它是第一个结点,它的locked域为false
* c. 线程B和C相继加入队列,a->next=b,b->next=c,B和C没有获取锁,处于等待状态,所以locked域为true,尾指针指向线程C对应的结点
* d. 线程A释放锁后,顺着它的next指针找到了线程B,并把B的locked域设置为false,这一动作会触发线程B获取锁。
public class MCSLock {
private final AtomicReference<Node> tail;
private final ThreadLocal<Node> myNode;
public MCSLock() {
tail = new AtomicReference<>();
myNode = ThreadLocal.withInitial(() -> new Node());
}
public void lock() {
Node node = myNode.get();
Node pred = tail.getAndSet(node);
if (pred != null) {
node.locked = true;
pred.next = node;
while (node.locked) {
}
}
}
public void unLock() {
Node node = myNode.get();
if (node.next == null) {
if (tail.compareAndSet(node, null)) {
return;
}
while (node.next == null) {
}
}
node.next.locked = false;
node.next = null;
}
class Node {
volatile boolean locked = false;
Node next = null;
}
public static void main(String[] args) {
MCSLock lock = new MCSLock();
Runnable task = new Runnable() {
private int a;
@Override
public void run() {
lock.lock();
for (int i = 0; i < 10; i++) {
a++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(a);
lock.unLock();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
最后
如果大家需要这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档的话麻烦点赞
CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
份清华大牛整理的进大厂必备的redis视频、面试题和技术文档的话麻烦点赞**
CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
[外链图片转存中…(img-Jy2dQxdx-1630921587215)]