`
wangzhangxing
  • 浏览: 2492 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

(转)MCS队列锁

阅读更多

原文:http://blog.csdn.net/aesop_wubo/article/details/7538934

简介

与CLH类似,MCS也是由QNode对象构成的链表,每个QNode表示一个锁持有者,表示一个线程要么已经获取锁,要么正在等待锁。它与CLH不同的是,队列是一个显示链表,是通过next指针串起来的。

 

实现

MCS队列锁的具体实现如下:

1、如图(a)所示,队列初始化时没有结点,tail=null;

2、如图(b)所示,线程A想要获取锁,于是将自己置于队尾,由于它是第一个结点,它的locked域为false;;

3、如果(c)所示,线程B和C相继加入队列,前面说了这个队列是由next指针串起来的,所以a->next=b,b->next=c。且B和C现在没有获取锁,处于等待状态,所以它们的locked域为true,尾指针指向线程C对应的结点;

4、如果(d)所示,线程A释放锁后,顺着它的next指针找到了线程B,并把B的locked域设置为false。这一动作会触发线程B获取锁。

从上面的实现可以看出,MSC与CLH最大的不同并不是链表是显示还是隐式,而是线程自旋的规则不同,CLH是在前趋结点的locked域上自旋等待,而MSC是在自己的结点的locked域上自旋等待。正因为如此,它解决了CLH在NUMA系统架构中获取locked域状态内存过远的问题。

下面看看MCS队列锁的JAVA实现:

 

  1. public class MCSLock implements Lock {  
  2.     AtomicReference<QNode> tail;  
  3.     ThreadLocal<QNode> myNode;  
  4.   
  5.     @Override  
  6.     public void lock() {  
  7.         QNode qnode = myNode.get();  
  8.         QNode pred = tail.getAndSet(qnode);  
  9.         if (pred != null) {  
  10.             qnode.locked = true;  
  11.             pred.next = qnode;  
  12.   
  13.             // wait until predecessor gives up the lock  
  14.             while (qnode.locked) {  
  15.             }  
  16.         }  
  17.     }  
  18.   
  19.     @Override  
  20.     public void unlock() {  
  21.         QNode qnode = myNode.get();  
  22.         if (qnode.next == null) {  
  23.             if (tail.compareAndSet(qnode, null))  
  24.                 return;  
  25.               
  26.             // wait until predecessor fills in its next field  
  27.             while (qnode.next == null) {  
  28.             }  
  29.         }  
  30.         qnode.next.locked = false;  
  31.         qnode.next = null;  
  32.     }  
  33.   
  34.     class QNode {  
  35.         boolean locked = false;  
  36.         QNode next = null;  
  37.     }  
  38. }  

lock方法:

 

若要获得锁,线程会把自己的结点放到队列的尾部,如果队列中开始有结点,就将前一个结点的next结点指向当前结点;

然后就在自己的locked域上自旋等待,直到它的前趋结点把自己的locked设置为false为止。

unlock方法:

若要释放锁,先检查自己的next域是否为null,如果为null,要么当前结点是尾结点,要么还有其他线程正在争用锁。不管是哪种情况都可以采用compareAndSet(q,null)来判断,其中q为当前结点,如果调用成功,则没有其他线程在争用锁,于是将tail设置为null返回;如果调用失败,说明另一个比较慢的线程正在试图获得锁,于是自旋等待它结束。在以上任一种情况,一旦出现有后继结点就将后续结点的locked域设置为false,然后返回。

 

疑点

对于unlock方法,有人会问既然qnode.next==null,说明qnode是尾结点,那么compareAndSet(q,null)为什么会失败呢?

如下图(a)所示,开始只有线程A在获取锁,A确实是队尾元素,tail指针也指向了它,多线程环境下,一切皆有可能,就在准备进行compareAndSet(q,null)操作时,突然以迅雷不及掩耳之势闯入两个线程B和C,如图(b)所示,这时如果再进行compareAndSet(q,null)操作就会失败。不过在这种情况下,while(qnode.next==null)会跳出循环,紧接着执行下面的两句代码:

 

  1. qnode.next.locked = false;  
  2. qnode.next = null;  

 

可见,释放锁操作在有线程闯入时也是能够正常工作的。

 

优缺点:

优点是适用于NUMA系统架构,缺点是释放锁也需要自旋等待,且比CLH读、写、CAS等操作调用次数多。

 

参考资料:

A simple correctness proof of the MCS contention-free lock

Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors

高性能自旋锁 MCS Spinlock 的设计与实现

The Art of Multiprocessor Programming

分享到:
评论

相关推荐

    bit转mcs说明

    在使用Xilinx FPGA进行硬件设计时,一个重要的步骤是将编译生成的bit文件转换为mcs文件。这个转换过程允许设计者将配置信息固化到FPGA内部的非易失性存储器中,从而确保即使在断电后重新上电,FPGA依然能够保留并...

    vivado bit文件格式转mcs文件格式

    ### Vivado中Bit文件转MCS文件的详细步骤与原理 #### 一、背景介绍 在数字电路设计领域,特别是FPGA(Field Programmable Gate Array)设计中,设计师经常需要将设计好的比特流文件(bit file)转换为MCS文件格式...

    MCS51 模数转换

    MCS51单片机是基于8051内核的一种广泛应用的微控制器,它在电子工程、自动化、物联网等领域有着广泛的应用。其中,模数转换(Analog-to-Digital Converter,简称ADC)是MCS51单片机中一个非常重要的功能,它允许...

    基于单片机MCS_51的智能密码锁设计

    基于MCS-51单片机的智能密码锁设计具有安全可靠、价格低廉、硬件电路简单等特点,非常适合家庭、办公室、宿舍等场所使用。此外,该设计还具备密码修改功能,使得在密码泄露的情况下也能轻松应对。通过软硬件的紧密...

    mcs51 电子密码锁

    mcs51 电子密码锁

    MCS9835CV 驱动

    MCS9835CV驱动是一款专为Windows NT、2K、XP以及2003操作系统设计的硬件驱动程序,它主要用于支持MCS9835CV芯片在这些系统中的正常运行。MCS9835CV是一款常用的串行ECP(Enhanced Capabilities Port)并行接口芯片,...

    802.11n的MCS速率

    802.11n引入了一种名为MCS(Modulation and Coding Scheme,调制与编码策略)的概念,通过不同的MCS索引值来配置和优化无线射频的速率。MCS索引是一个关键参数,它关联了一组特定的调制方式和编码率,从而确定了在...

    从MCS51 向AVR 的快速转换

    从MCS51向AVR的快速转换:深入解析与应用策略 广州天河双龙电子有限公司的专家詹卫前在其文章《从MCS51向AVR的快速转换》中,详细介绍了如何让原本熟悉MCS51单片机的使用者能够迅速掌握并应用ATMEL的AVR系列单片机...

    从MCS51 向AVR 的快速转换教程 PDF

    ### 从MCS51向AVR的快速转换教程知识点详解 #### 一、AVR与MCS51的关键区别及优势 **1. 性能优化:** - **AVR机器周期与指令周期:** AVR系列单片机的一个显著特点是它的机器周期仅等于1个时钟周期,而且大部分...

    Vivado2018.3生成和加载mcs文件详细过程.docx

    Vivado2018.3生成和加载mcs文件详细过程 Vivado2018.3是Xilinx公司推出的一个基于PC的 FPGA开发环境,提供了一个集成的开发环境,包括设计、仿真、编译、下载和调试等多种功能。其中,生成和加载mcs文件是Vivado...

    新编MCS-51单片机应用设计(清晰最新版)

    本书是在第3版《MCS:51单片机应用设计》一书的基础上,从应用的角度,详细地介绍了MCS:51单片机的硬件结构、指令系统、各种硬件接口设计、各种常用的数据运算和处理程序、接口驱动程序以及MCS:51单片机应用系统的...

    MCS9904.zip

    总的来说,"MCS9904.zip"压缩包包含了各种PCI转COM驱动,以及USB 3.0转COM的相关驱动,适用于需要扩展或升级系统串行接口的场合。这些驱动程序使得用户能够顺利地在现代系统上使用传统的串行设备,或者利用高速USB ...

    Intel MCS 51系列datasheet

    - **中断请求**:当某个中断源产生中断信号时,如果当前没有更高级别的中断正在处理,则CPU会暂停当前指令的执行,转而执行相应的中断服务程序。 - **中断响应**:CPU在接收到中断请求后,会保存当前的状态信息,并...

    mcs9900_linux驱动

    《MCS9900 Linux驱动详解》 在嵌入式系统和工业自动化领域,通信接口的稳定性与效率至关重要。MCS9900是一款专为PCI-E接口设计的串行通信芯片,它能将PCI-E接口转换为多个串行接口,如RS-232、RS-485等,广泛应用于...

    MCS spinlock的Linux内核模块实现.pdf

    1. MCS Spinlock 的基本原理:MCS Spinlock 是一种基于链表的自旋锁机制,每个线程都有一个自己的链表节点,当线程需要访问共享资源时,需要先申请锁,并将自己的链表节点加入到链表中。 2. MCS Spinlock 的实现:...

    mcs9865资料全部

    【mcs9865资料全部】是一份包含有关mcs9865集成电路全面信息的资源集合。这个压缩包提供了该芯片的关键技术文档,包括 datasheet、参考电路图(schematic)、PCB手册以及电路设计和驱动设置的工具。mcs9865是一款在...

    Motorola MCS2000维修手册

    《Motorola MCS2000维修手册》是一本专门针对摩托罗拉MCS2000系列对讲机的维护和技术指南。这份手册是英文原版,内容详尽且专业,旨在帮助无线电通信技术人员和爱好者了解和修复MCS2000对讲机可能出现的各种问题。...

    MCS9865Win32

    《MCS9865 Win32驱动程序详解》 MCS9865是一款针对Windows 32位操作系统设计的驱动程序,该程序的主要功能是为计算机提供与MCS9865设备的交互支持。这个驱动版本为v1.0.0.10,获得了微软WHQL(Windows Hardware ...

    MCS-51 examples

    MCS-51系列单片机是Intel公司推出的一种8位微处理器,广泛应用于工业控制、消费电子、汽车电子等领域。这个压缩包“MCS-51 examples”显然是为学习和理解MCS-51单片机编程提供了一系列实例代码。下面我们将详细探讨...

    基于MCS7840的USB转四串口设计

    这是基于MCS7840的USB转四串口设计,简化了原厂的设计方案,可以根据自己的需求修改。至少做电源的隔离,也可以把地隔离也都做了,本人因为使用双层板制作,未做模拟地和数字地的隔离。设计使用cadence软件,已将...

Global site tag (gtag.js) - Google Analytics