CLH 锁

简介:

概述

CLH锁是一种自旋锁,能确保无饥饿性,提供先来先服务的公平性。所谓的自旋是指:当线程试图去拿已经被其它线程占有的锁时,当前线程不会进入阻塞态,而是进入一个死循环去自旋的获取锁,获取到锁之后退出死循环。
同时CLH锁也是一种基于链表的可扩展,高性能,公平的自旋锁,申请线程只在本地变量上自旋轮询前驱的状态,如果发现前驱释放了锁就结束自旋。

实验


public class CLHLock implements Lock {
    private final AtomicReference<QNode> tail;
    private final ThreadLocal<QNode> myPred;
    private final ThreadLocal<QNode> myNode;

    public CLHLock() {
        tail = new AtomicReference<QNode>(new QNode());
        myNode = new ThreadLocal<QNode>() {
            protected QNode initialValue() {
                return new QNode();
            }
        };

        myPred = new ThreadLocal<QNode>();
    }
    
    private static class QNode {
        volatile boolean locked;
    }

    @Override
    public void lock() {
        QNode node = (QNode) myNode.get();
        node.locked = true;
        QNode pred = (QNode) tail.getAndSet(node);
        myPred.set(pred);
        while (pred.locked) {
        }
    }

    @Override
    public void unlock() {
        QNode node = (QNode) myNode.get();
        node.locked = false;
        myNode.set(null);
        myPred.set(null);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public boolean tryLock() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public Condition newCondition() {
        // TODO Auto-generated method stub
        return null;
    }
}
public class CLHLockTest {
    public static  int tmp = 0;
    public static CLHLock lock = new CLHLock();
    
    public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();
            new Thread(new Run()).start();       
        }    
        System.out.println(CLHLockTest.tmp);
    }
}

class Run implements Runnable {

    @Override
    public void run() {        
        CLHLockTest.lock.lock();
        CLHLockTest.tmp++;
        CLHLockTest.lock.unlock();    
    }    
}

CLHLock使用tail 这个变量来标记队尾,当每个线程执行lock操作的时候,会生成相对应的myPred(指向前一个线程,以便监听前一个线程的执行情况,如果前一个线程myNode.locked = true, 这个线程会一直执行死循环来自旋;如果前一个线程myNode.locked = false; 这个线程就可以获取到锁了),myNode(用来给它的后继节点作为监听对象)的线程局部变量。当一个线程获取到锁后进行解锁时:它会获取自身的myNode,将其中的locked 标志位置为 false, 这样它的后继节点就可以从死循环中跳出来了(拿到锁了)。

如有错误希望大家能指出来
参考资料:
http://www.cnblogs.com/yuyutianxia/p/4296220.html
http://googi.iteye.com/blog/1736570

目录
相关文章
|
Java
jdk 8 使用okhttp3 实现 http2
使用jdk8 使用okhttp3 实现http2请求
4069 0
jdk 8 使用okhttp3 实现 http2
|
3月前
|
人工智能 运维 监控
阿里云 API 聚合实战:破解接口碎片化难题,3 类场景方案让业务响应提速 60%
API聚合破解接口碎片化困局,助力开发者降本增效。通过统一中间层整合微服务、第三方接口与AI模型,实现调用次数减少60%、响应提速70%。阿里云实测:APISIX+函数计算+ARMS监控组合,支撑百万级并发,故障定位效率提升90%。
321 0
|
9月前
|
存储 安全 Linux
【实战指南】7个设置/获取接口了解Linux时间管理
本文系统介绍了Linux时间管理中的7个关键设置/获取接口,涵盖时间获取(如`time`、`gettimeofday`、`clock_gettime`)、时间设置(如`stime`、`settimeofday`、`clock_settime`)以及时间转换和格式化等内容。文章详细解析了绝对时间和相对时间的概念,包括GMT、UTC及本地时间的区别,并通过实例测试展示了各接口的使用方法与特性。此外,还探讨了时区设置对时间计算的影响,强调在实际开发中推荐使用UTC作为基准时间以避免时区变化带来的问题。总结部分结合项目经验,提醒开发者注意时间服务的重要性及潜在风险,例如时间跳跃可能引发的应用故障。
548 107
【实战指南】7个设置/获取接口了解Linux时间管理
|
3月前
|
SQL 人工智能 Linux
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
417 5
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
|
存储 消息中间件 缓存
系统设计面试参考-设计Spotify系统
【10月更文挑战第4天】支持用户将自己喜欢的音乐、专辑、播放列表等分享到社交媒体平台,如 Facebook、Twitter、Instagram 等。分享内容可以包括音乐链接、封面图片、简介等信息,吸引更多的用户来使用 Spotify 系统。同时,系统可以跟踪分享的效果,如点击量、转化率等,以便评估社交分享对系统推广的贡献。
415 5
|
机器学习/深度学习 人工智能 自然语言处理
ChatGPT的名字由
【10月更文挑战第13天】
540 0
|
9月前
|
人工智能 运维 API
云栖大会 | Terraform从入门到实践:快速构建你的第一张业务网络
云栖大会 | Terraform从入门到实践:快速构建你的第一张业务网络
426 1
|
JavaScript
Vue路由传参实战指南:三种常用方法示例演示
Vue路由传参实战指南:三种常用方法示例演示
682 0
|
网络协议 Java 程序员
【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用
【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用
678 2
|
Python
SyntaxError: Non-ASCII character 与 Cannot decode using encoding "ascii" 错误解决
在Python调试中遇到的两种编码错误:1) &quot;Cannot decode using encoding &#39;ascii&#39;&quot;,此错误发生在处理含有非ASCII字节的字符串时;2) &quot;SyntaxError: Non-ASCII character&quot;,当程序文件含中文且未声明编码。解决方法是在脚本开头添加 &quot;# -*- coding: utf-8 -*-&quot; 或 &quot;#coding=UTF-8&quot;,告知Python使用UTF-8解析,确保文件实际也以UTF-8编码保存。
597 0