JAVA锁---------------------CLH锁和MCS锁

本文详细介绍了CLH锁和MCS锁两种自旋锁的实现原理及代码实现。CLH锁通过查询前驱变量实现锁的获取与释放,而MCS锁在此基础上增加了真实的后继节点,更适合NUMA架构。两种锁都是公平锁,但在激烈的竞争环境下可能导致性能下降。

       参考:http://ifeve.com/java_lock_see2/

一:CLH锁

  1. 实现
    package com.eden.coreLearn.thread.lock;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
    
    import org.junit.Test;
    
    /**
     * CLH自旋锁
     * 
     * @author eden.ding1991@gmail.com 2016年7月15日 下午5:39:38
     */
    public class CLHLock {
    
        public static class CLHNode {
            private volatile boolean isLocked = true;
        }
    
        @SuppressWarnings("unused")
        private volatile CLHNode tail;
    
        private static final ThreadLocal<CLHNode> nodeLocal = new ThreadLocal<CLHNode>();
    
        //构建一个CLHLock对象中变量名为tail,类型为CLHNode的原子更新器(该变量必须有volatile关键字修饰)
        private static final AtomicReferenceFieldUpdater<CLHLock, CLHNode> updater   = AtomicReferenceFieldUpdater
                .newUpdater(CLHLock.class, CLHNode.class, "tail");
    
        public void lock() {
            CLHNode node = new CLHNode();
            nodeLocal.set(node);
            CLHNode preNode = updater.getAndSet(this, node);
            //        System.out.println(String.format("preNode=%s", preNode));
            if (preNode != null) {
                while (preNode.isLocked) {
    
                }
                preNode = null;
                nodeLocal.set(node);//没看懂为什么又要set一次
            }
        }
    
        public void unlock() {
            CLHNode node = nodeLocal.get();//获取当前线程锁的节点
            if (!updater.compareAndSet(this, node, null)) {
                node.isLocked = false;
            }
            node = null;
        }
    
        @Test
        public void testCLHLock() throws InterruptedException {
            Student st = new Student(new CLHLock());
            for (int i = 0; i < 100; i++) {
                new Thread(new CLHLockThread(st), i + "").start();
            }
            TimeUnit.SECONDS.sleep(30);
        }
    
        public class Student {
            private int     i = 0;
    
            private CLHLock lock;
    
            public Student(CLHLock lock) {
                this.lock = lock;
            }
    
            public void add() {
                lock.lock();
                this.i = this.i + 1;
                System.out.println(String.format("线程%s的变量i=%s", Thread.currentThread().getName(), this.i));
                //            lock.unlock();
            }
        }
    
        public class CLHLockThread extends Thread {
            private Student st;
    
            public CLHLockThread(Student st) {
                this.st = st;
            }
    
            @Override
            public void run() {
                st.add();
            }
        }
    }
    

  2. CLH锁是通过不停的查询前驱变量preNode来实现的,是隐式的队列,并没有真实的后继节点
  3. lock函数实现:调用lock的时候,先新建一个自己的tail node节点,并存到自己的线程栈里,然后通过updater获取共享的tail node并将共享的tail node更新成自己的tail node,如果共享的tail node不为空,则获取锁失败,执行空轮询,反之成功
  4. unlock函数实现,先取出当前线程的tail node节点,并与共享的tail node节点比较,如果相同,则释放锁,同时将共享的tail node更新成null
  5. CLH锁也是公平锁,遵循先来后到的顺序,但是和其他自旋锁一样,竞争激烈时会导致性能下降

二:MCS锁

  1. 实现
    package com.eden.coreLearn.thread.lock;
    
    import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
    
    /**
     *
     * @author eden.ding1991@gmail.com 2016年7月15日 下午6:36:40
     */
    public class MCSLock {
    
        public class MCSNode {
            private volatile MCSNode next;
            private volatile boolean isLocked = true;
        }
    
        private static final ThreadLocal<MCSNode> nodeLocal = new ThreadLocal<MCSNode>();
        
        @SuppressWarnings("unused")
        private volatile MCSNode node;
        
        private static final AtomicReferenceFieldUpdater<MCSLock, MCSNode> updater   = AtomicReferenceFieldUpdater
                .newUpdater(MCSLock.class, MCSNode.class, "node");
    
        public void lock() {
            MCSNode current = new MCSNode();
            nodeLocal.set(current);
            MCSNode preNode = updater.getAndSet(this, current);
            if (preNode != null) {
                preNode.next = current;
                while (current.isLocked) {
    
                }
            }
        }
    
        public void unlock() {
            MCSNode current = nodeLocal.get();
            if (current.next == null) {
                if (updater.compareAndSet(this, current, null)) {
    
                } else {
                    while (current.next == null) {
    
                    }
                }
            } else {
                current.next.isLocked = false;
                current.next = null;
            }
        }
    
    }
    

  2. 实现其实再CLH锁的基础上加了真实的后继节点
  3. CLHlock是不停的查询前驱变量, 导致不适合在NUMA 架构下使用(在这种结构下,每个线程分布在不同的物理内存区域,MCSLock则是对本地变量的节点进行循环。不存在CLHlock 的问题。
在没有直接引用内容的情况下,将基于现有知识对 **mf30D-clh** 进行分析信息整合。该标识可能属于某个特定设备、模块或技术组件,通常以类似命名方式出现在工业控制、嵌入式系统或通信设备中。 ### 产品型号与技术标识解析 **mf30D-clh** 的命名结构表明其可能为某类模块化设备或控制器。例如: - **"mf"** 可能代表“多功能”(Multi-Function)。 - **"30D"** 通常表示型号或性能等级,如处理能力、内存大小或接口数量。 - **"clh"** 可能是特定版本标识,例如“Closed Housing”(封闭外壳)、“Controller Low Heat”(低发热控制器)或其他定制化描述。 ### 技术规格(推测) 尽管无法获取确切数据,但可以基于命名惯例推测其可能具备以下技术特性: - **处理器架构**:ARM Cortex-M 或 Cortex-A 系列,视应用需求而定。 - **内存配置**:可能配备 32MB 至 256MB 的闪存与 RAM,支持固件升级数据缓存。 - **通信接口**:包括但不限于 UART、SPI、I2C、CAN、以太网或 Wi-Fi/蓝牙模块[^1]。 - **电源要求**:典型 5V 或 24V DC 输入,适应工业环境。 - **工作温度范围**:-20°C 至 +70°C,适用于工业级应用场景。 ### 用途与应用场景 **mf30D-clh** 可能应用于以下领域: - 工业自动化控制单元,如 PLC(可编程逻辑控制器)或远程 I/O 模块。 - 智能楼宇管理系统中的数据采集与控制节点。 - 物联网边缘设备,用于传感器数据聚合与本地处理。 - 通信网关,负责协议转换与数据转发。 ### 编程与配置示例 如需对其进行配置,通常通过串口或网络接口进行参数设置。以下是基于串口配置的伪代码示例: ```python import serial # 打开端口 ser = serial.Serial('COM3', 9600, timeout=1) # 发送配置命令 ser.write(b'CONFIGURE mf30D-clh SET IP=192.168.1.100 PORT=502\r\n') # 读取响应 response = ser.readline() print(response.decode('utf-8')) # 关闭端口 ser.close() ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值