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

JAVA并发编程学习笔记之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实现:
[java] view plaincopyprint?
public class MCSLock implements Lock { 
    AtomicReference<QNode> tail; 
    ThreadLocal<QNode> myNode; 
 
    @Override 
    public void lock() { 
        QNode qnode = myNode.get(); 
        QNode pred = tail.getAndSet(qnode); 
        if (pred != null) { 
            qnode.locked = true; 
            pred.next = qnode; 
 
            // wait until predecessor gives up the lock 
            while (qnode.locked) { 
            } 
        } 
    } 
 
    @Override 
    public void unlock() { 
        QNode qnode = myNode.get(); 
        if (qnode.next == null) { 
            if (tail.compareAndSet(qnode, null)) 
                return; 
             
            // wait until predecessor fills in its next field 
            while (qnode.next == null) { 
            } 
        } 
        qnode.next.locked = false; 
        qnode.next = null; 
    } 
 
    class QNode { 
        boolean locked = false; 
        QNode next = null; 
    } 

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)会跳出循环,紧接着执行下面的两句代码:
[java] view plaincopyprint?
qnode.next.locked = false; 
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
分享到:
评论

相关推荐

    MCS-51单片机学习笔记

    《MCS-51单片机学习笔记》 MCS-51单片机,作为微型计算机的一种,遵循冯诺依曼的计算机架构原理,主要包括输入、处理和输出三大部分。其中,输入输出通过I/O接口实现,处理则依赖于处理器和存储器。MCS-51单片机的...

    并发数据结构与多核编程21-22秋季1

    课程详细讨论了不同的锁机制,如TAS锁、TTAS锁、回退锁、队列锁(CLH队列锁和MCS队列锁)以及超时锁。此外,还涉及了管程和阻塞同步,以及读-写锁、可重入锁和信号量等同步机制在链表操作中的应用。 并发数据结构是...

    MCS-51单片机C语言编程100例.rar

    《MCS-51单片机C语言编程100例》是一份专注于STC单片机编程的实践教程,其核心是通过100个实际的C语言编程实例,帮助学习者掌握MCS-51系列单片机的使用技巧和应用方法。这份资源特别强调了STC15F2K60S2型号的单片机...

    基于C语言编程MCS-51单片机原理与应用

    《基于C语言编程MCS-51单片机原理与应用》是一本深入探讨MCS-51系列单片机的书籍,它结合了C语言编程技术,为读者提供了全面而实用的知识体系。MCS-51单片机是Intel公司推出的8位微处理器,广泛应用于工业控制、家用...

    基于c语言编程mcs-51单片机原理与应用

    学习MCS-51单片机和C语言编程,需要理论与实践相结合,通过编写简单的程序并利用开发板进行验证,逐步掌握单片机的使用和C语言编程技巧。 总之,基于C语言编程的MCS-51单片机是一个强大的工具,它将理论知识与实际...

    学习笔记之&nbsp;单片机编程之C语言.doc

    【学习笔记之单片机编程之C语言】 在学习单片机编程,特别是使用C语言进行AVR单片机编程时,理解硬件特性和编程注意事项是至关重要的。AVR单片机是由Atmel(现被Microchip收购)开发的一系列高性能、低功耗的微控制...

    MCS-51单片机经典实验C语言编程

    《MCS-51单片机经典实验C语言编程》是一个专为大学生设计的学习资源,旨在帮助他们掌握MCS-51单片机的基础知识和C语言编程技巧。MCS-51,又称为8051单片机,是微控制器领域中的一种经典型号,广泛应用于各种嵌入式...

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

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

    MCS51系列学习软件 单片机学习

    2. **汇编语言编程**:MCS51主要采用汇编语言进行编程,软件中可能包含了大量的汇编语言程序示例,从基本指令到复杂的程序设计,让学习者逐步掌握编写汇编程序的技巧。 3. **C语言编程**:虽然MCS51以汇编为主,但...

    MCS51入门教程和编程实例30篇

    本教程旨在帮助初学者快速掌握MCS51的使用和编程技巧,通过30个具体的实例,逐步深入讲解相关知识。 首先,了解MCS51的硬件结构至关重要。它包含了CPU、存储器、定时器/计数器、中断系统、并行I/O端口等多个核心...

    基于C语言的MCS-51编程应用.pdf

    "基于C语言的MCS-51编程应用" 在本文中,我们将介绍基于C语言的MCS-51编程应用,讨论MCS-51单片机的编程技术和应用领域。 一、 MCS-51单片机的介绍 MCS-51单片机是一种8位单片机,由Intel公司开发,广泛应用于...

    MCS-51单片机C语言编程100例

    通过学习《MCS-51单片机C语言编程100例》,读者不仅可以熟悉51单片机的硬件结构和C语言编程,还能培养解决问题的能力,为后续的嵌入式系统设计和开发打下坚实的基础。对于电子爱好者、工程技术人员以及相关专业的...

    普罗格 intplog MCS控制系统mcs JAVA项目源码

    普罗格 intplog MCS控制系统mcs JAVA项目源码 @Autowired private InterfaceLogService interfaceLogService; @Autowired private McsPlcLogService mcsPlcLogService; //1F分拣口 public void Distribution1F...

    mcs-51 单片机 编程(学习资料2)

    **MCS-51单片机编程学习资料2概述** MCS-51单片机是一种广泛应用的8位微处理器,由Intel公司开发,广泛应用于嵌入式系统设计。这份学习资料2涵盖了多个关于MCS-51单片机编程的关键主题,包括硬件接口、指令系统、...

    07-Java基础(数组-常见问题)

    Java语言中的数组是编程中最基本的数据结构之一,它允许存储同一类型的数据集合。在这个主题“07-Java基础(数组-常见问题)”中,我们将深入探讨数组在Java编程中的一些常见问题及其解决方案。 1. **数组的声明与...

    mcs51 电子密码锁

    mcs51 电子密码锁

    MCS_51单片机学习笔记

    适用于STC89c58单片机学习,适用于STC89c58单片机学习,适用于STC89c58单片机学习,适用于STC89c58单片机学习,适用于STC89c58单片机学习

    MCS-51 examples

    这个压缩包“MCS-51 examples”显然是为学习和理解MCS-51单片机编程提供了一系列实例代码。下面我们将详细探讨MCS-51单片机的基本结构、指令系统以及常见的应用示例。 一、MCS-51单片机概述 MCS-51,又称8051,是一...

Global site tag (gtag.js) - Google Analytics