CLH自旋锁是一种基于隐式链表(节点里面没有next指针)的可扩展、高性能、公平的自旋锁,申请线程只在本地变量上自旋,它不断轮询前驱的状态,如果发现前驱释放了锁就结束自旋。CLH队列锁的优点是空间复杂度低(如果有n个线程,L个锁,每个线程每次只获取一个锁,那么需要的存储空间是O(L+n),n个线程有n个。myNode,L个锁有L个tail),CLH的一种变体被应用在了JAVA并发框架中。 CLH在SMP系统结构下该法是非常有效的。但在NUMA系统结构下,每个线程有自己的内存,如果前趋结点的内存位置比较远,自旋判断前趋结点的locked域,性能将大打折扣。
示例代码如下:
import java.util.concurrent.atomic.AtomicReference;运行效果
public class HelloWorld {
public static void main(String[] args) throws InterruptedException {
CLHLock lock=new CLHLock();
Runnable runnable=new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" 获得锁 ");
//前驱释放,do own work
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName()+" 释放锁 ");
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t1=new Thread(runnable,"线程1");
Thread t2=new Thread(runnable,"线程2");
Thread t3=new Thread(runnable,"线程3");
t1.start();
t2.start();
t3.start();
}
}
/**
* Created by qindongliang on 2018/8/5.
*/
class CLHLock {
class Node{
//false代表没人占用锁
volatile boolean locked=false;
}
//指向最后加入的线程
final AtomicReference<Node> tail=new AtomicReference<>(new Node());
//使用ThreadLocal保证每个线程副本内都有一个Node对象
final ThreadLocal<Node> current;
public CLHLock(){
//初始化当前节点的node
current=new ThreadLocal<Node>(){
@Override
protected Node initialValue() {
return new Node();
}
};
}
public void lock() throws InterruptedException {
//得到当前线程的Node节点
Node own=current.get();
//修改为true,代表当前线程需要获取锁
own.locked=true;
//设置当前线程去注册锁,注意在多线程下环境下,这个
//方法仍然能保持原子性,,并返回上一次的加锁节点(前驱节点)
Node preNode=tail.getAndSet(own);
//在前驱节点上自旋
while(preNode.locked){
System.out.println(Thread.currentThread().getName()+" 开始自旋.... ");
Thread.sleep(2000);
}
}
public void unlock(){
//当前线程如果释放锁,只要将占用状态改为false即可
//因为其他的线程会轮询自己,所以volatile布尔变量改变之后
//会保证下一个线程能立即看到变化,从而得到锁
current.get().locked=false;
}
}
网友回复
python如何调用openai的api实现知识讲解类动画讲解视频的合成?
html如何直接调用openai的api实现海报可视化设计及文本描述生成可编辑海报?
f12前端调试如何找出按钮点击事件触发的那段代码进行调试?
abcjs如何将曲谱播放后导出mid和wav格式音频下载?
python如何将曲子文本生成音乐mp3或wav、mid文件
python中mp3、wav音乐如何转成mid格式?
js在HTML中如何将曲谱生成音乐在线播放并下载本地?
python如何实现在windows上通过键盘来模拟鼠标操作?
python如何给win10电脑增加文件或文件夹右键自定义菜单?
python如何将音乐mp3文件解析获取曲调数据?