`

硬件同步原语(CAS)理论

阅读更多

在Java并发编程中,常常出现一些因为线程安全问题而需要加锁来保证同步,而在Java5之后,出现了新的并发包,它的出现使得同步效率更加高效,而所有concurrent包的理论基础都是基于硬件同步原语理论,它是基于Cpu硬件的同步,效率比软件中通过锁定(排它锁)效率高。

 

大多数现代处理器都包含对多处理的支持。当然这种支持包括多处理器可以共享外部设备和主内存,同时它通常还包括对指令系统的增加来支持多处理的特殊要求。特别是,几乎每个现代处理器都有通过可以检测或阻止其他处理器的并发访问的方式来更新共享变量的指令。

比较并交换 (CAS)

支持并发的第一个处理器提供原子的测试并设置操作,通常在单位上运行这项操作。现在的处理器(包括 Intel 和 Sparc 处理器)使用的最通用的方法是实现名为 比较并转换 或 CAS 的原语。(在 Intel 处理器中,比较并交换通过指令的 cmpxchg 系列实现。PowerPC 处理器有一对名为“加载并保留”和“条件存储”的指令,它们实现相同的目地;MIPS 与 PowerPC 处理器相似,除了第一个指令称为“加载链接”。)

CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无 论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。”

通常将 CAS 用于同步的方式是从地址 V 读取值 A,执行多步计算来获得新值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功。

类似于 CAS 的指令允许算法执行读-修改-写操作,而无需害怕其他线程同时修改变量,因为如果其他线程修改变量,那么 CAS 会检测它(并失败),算法可以对该操作重新计算。清单 3 说明了 CAS 操作的行为(而不是性能特征),但是 CAS 的价值是它可以在硬件中实现,并且是极轻量级的(在大多数处理器中):


清单 3. 说明比较并交换的行为(而不是性能)的代码

				
        
public class SimulatedCAS {
    private int value;
    
    public synchronized int getValue() { return value; }
    
    public synchronized int compareAndSwap(int expectedValue, int newValue) {
        if (value == expectedValue) 
            value = newValue;
        return value;
    }
}
      

 

使用 CAS 实现计数器

基于 CAS 的并发算法称为 无锁定 算 法,因为线程不必再等待锁定(有时称为互斥或关键部分,这取决于线程平台的术语)。无论 CAS 操作成功还是失败,在任何一种情况中,它都在可预知的时间内完成。如果 CAS 失败,调用者可以重试 CAS 操作或采取其他适合的操作。清单 4 显示了重新编写的计数器类来使用 CAS 替代锁定:


清单 4. 使用比较并交换实现计数器

				
        
public class CasCounter {
    private SimulatedCAS value;
    public int getValue() {
        return value.getValue();
    }
    public int increment() {
        int oldValue = value.getValue();
        while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue)
            oldValue = value.getValue();
        return oldValue + 1;
    }
}
      





回页首


无锁定且无等待算法

如果每个线程在其他线程任意延迟(或甚至失败)时都将持续进行操作,就可以说该算法是 无等待 的。与此形成对比的是, 无锁定 算法要求仅 某个 线程总是执行操作。(无等待的另一种定义是保证每个线程在其有限的步骤中正确计算自己的操作,而不管其他线程的操作、计时、交叉或速度。这一限制可以是系统中线程数的函数;例如,如果有 10 个线程,每个线程都执行一次 CasCounter.increment() 操作,最坏的情况下,每个线程将必须重试最多九次,才能完成增加。)

再过去的 15 年里,人们已经对无等待且无锁定算法(也称为 无阻塞算法 ) 进行了大量研究,许多人通用数据结构已经发现了无阻塞算法。无阻塞算法被广泛用于操作系统和 JVM 级别,进行诸如线程和进程调度等任务。虽然它们的实现比较复杂,但相对于基于锁定的备选算法,它们有许多优点:可以避免优先级倒置和死锁等危险,竞争比较 便宜,协调发生在更细的粒度级别,允许更高程度的并行机制等等

分享到:
评论
4 楼 fbwfbi 2015-07-31  
fengchuizhuming 写道
楼主的完全正确。鉴定完毕


楼上完全错误,已证明。 CAS 有两种形式,一种是不管操作成功与否,都是返回原值(旧),另一种就是就是返回True 或 False , 楼主给出的代码描述是错的。标准的如下:

引用

CAS原子操作在维基百科中的代码描述如下:
   1: int compare_and_swap(int* reg, int oldval, int newval)
   2: {
   3:   ATOMIC();
   4:   int old_reg_val = *reg;
   5:   if (old_reg_val == oldval)
   6:      *reg = newval;
   7:   END_ATOMIC();
   8:   return old_reg_val;
   9: }
也就是检查内存*reg里的值是不是oldval,如果是的话,则对其赋值newval。上面的代码总是返回old_reg_value,调用者如果需要知道是否更新成功还需要做进一步判断,为了方便,它可以变种为直接返回是否更新成功,如下:
   1: bool compare_and_swap (int *accum, int *dest, int newval)
   2: {
   3:   if ( *accum == *dest ) {
   4:       *dest = newval;
   5:       return true;
   6:   }
   7:   return false;
   8: }
3 楼 fengchuizhuming 2014-12-05  
楼主的完全正确。鉴定完毕
2 楼 bhtbed 2013-01-17  
一楼请考虑多线程的情况,这个value会被其他线程在其他地方改变,在int oldValue = value.getValue();之后,while之前 线程调度发生的时候。
不过这个while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue)确实有问题,当成功的时候,increase会增加2,不是1.

另外,之所以很多实现返回bool,是为了更清楚到底成功没,像你这样的实现并不清楚CAS到底是否成功。
C#的实现是:bool CompareExchange(ref object location, object value,object newValue)。
感觉更好,通过传入ref,即能修改值为最新值,同时bool返回是否设置新值成功。
1 楼 youfengkai 2011-02-10  
while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue)
            oldValue = value.getValue();
        return oldValue + 1;
这个例子让我很晕,费解.


value.compareAndSwap(oldValue, oldValue + 1) != oldValue,这个不是恒等式么?

相关推荐

    ARM架构硬件同步原语

    ARM架构的硬件同步原语是嵌入式系统和设备驱动程序开发中的关键概念,尤其是在Linux内核编程中。这些原语允许多个处理器核在没有软件干预的情况下协调对共享资源的访问,确保数据一致性并避免竞争条件。在多核ARM...

    任务二-同步原语实现1

    同步原语实现的知识点总结 本文总结了操作系统研讨课中Project 4 Task 2的同步原语实现的知识点,涵盖了condition variables、semaphores和barriers三种同步原语的实现机制、数据结构和函数实现。 一、同步原语...

    ARM同步原语synchronization primitives

    ### ARM同步原语详解 #### 一、引言 随着多核处理器的普及与高性能计算需求的增长,确保多线程程序正确同步变得至关重要。ARM体系结构作为一种广泛应用的嵌入式系统架构,在同步机制方面提供了丰富的支持。本文档...

    ecos系统同步原语

    【ecos系统同步原语详解】 在嵌入式操作系统ecos中,为了处理多线程环境中的并发执行问题,如线程协同、资源竞争、线程间通信和同步,ecos内核提供了一系列的同步原语。这些原语主要包括互斥、条件变量、信号量、...

    FPGA全局时钟资源相关原语及使用

    FPGA全局时钟资源是指在场可编程门阵列(Field Programmable Gate Array, FPGA)设计中,用于确保芯片内部时钟信号同步和精确分布的专用硬件资源。这些资源通常由全铜层工艺实现,并通过专用时钟缓冲和驱动结构优化...

    同步机构 模拟实现同步机构 操作系统实验

    一般说,同步机构是由若干条原语——同步原语——所组成。本实验要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。 三. 实验题目 模拟PV操作同步机构,且用PV操作解决...

    如何用PV原语实现进程间的互斥与同步

    在计算机科学领域,特别是操作系统理论中,PV操作是用于控制并发进程之间互斥与同步的关键机制之一。PV操作(也称作信号量操作)是由荷兰科学家Edsger W. Dijkstra提出的一种原子性操作,主要包括两种类型:P操作...

    cpp11-on-multicore, 在C 11中,多线程应用程序的各种同步原语.zip

    cpp11-on-multicore, 在C 11中,多线程应用程序的各种同步原语 C 11中多线程应用程序的各种同步原语。在博客文章中,信号量是令人惊讶的。代码是在许可协议下发布的。 查看 LICENSE 文件。如何构建测试首先,你必须...

    并发编程实践,全面介绍基础知识、JVM同步原语、线程安全、低级并发工具、线程安全容器、高级线程协作工具、Executor部分等

    本文将全面介绍Java并发编程的基础知识、JVM同步原语、线程安全、低级并发工具、线程安全容器、高级线程协作工具以及Executor服务。 1. **基础知识** - **并发与并行**:并发是指多个任务在同一时间段内交替执行,...

    cpp-plibsys高可移植的C系统库线程和同步原语套接字

    高可移植的C系统库:线程和同步原语,套接字(TCP,UDP,SCTP),IPv4和IPv6,IPC,散列函数(MD5,SHA-1,SHA-2,SHA-3,GOST),二进制树 ,AVL)等等。 本地代码性能。

    Python-fifolock一个灵活的低级工具用于在asyncioPython中创建同步原语

    在异步编程中,同步原语是至关重要的,它们帮助我们控制对共享资源的访问,避免竞争条件和死锁。本文将深入探讨`fifolock`,一个专为asyncio设计的灵活低级同步工具。 `fifolock`源自Python社区的一个开源项目,它...

    多线程leetcode-syncx:Go中更高级的同步原语

    更高级的同步原语。 实现了一些 Go 同步原语。 令牌 提供令牌实现。 只有拥有Token才能做事,然后才能将令牌移交给其他人。 批 提供批量实现。 类似于errgroup ,可以返回每个任务的所有错误结果。 任何 提供部分...

    7Series和ultrascale原语的详解文档.zip

    本篇文章将深入探讨这两个系列的原语,并结合Verilog和VHDL这两种硬件描述语言进行讲解。 7Series原语是Xilinx针对其7系列FPGA设计的底层逻辑单元。这些原语包括但不限于: 1. LUT(查找表):LUT是FPGA中的基本...

    Xilinx原语的使用方法.pdf

    在FPGA设计中,原语是通过硬件描述语言(如VHDL或Verilog)直接实例化的最基本构建块,它们映射到FPGA内部的特定硬件资源,如查找表(LUTs)、寄存器、专用乘法器等。 在本文档“Xilinx原语的使用方法.pdf”中,...

    parking_lot:用于Rust的紧凑高效的同步原语。 还提供了用于创建自定义同步原语的API

    它还公开了用于创建您自己的有效同步原语的低级API。 在x86_64 Linux上进行测试时,发现parking_lot::Mutex速度比std::sync::Mutex速度快1.5倍,而在多线程竞争时,速度最高可快5倍。 RwLock的数字取决于读取器和...

    xilinx V6 原语代码

    "Xilinx V6 原语代码"指的是针对V6系列FPGA的底层硬件描述语言(HDL)代码,通常使用VHDL(VHSIC Hardware Description Language)或Verilog进行编写。这些原语代码是FPGA设计的核心部分,它们定义了FPGA内部的基本...

    Xilinx原语详解

    5. **PLL和DLL**:PLL(Phase-Locked Loop)原语可以生成多个时钟,用于同步系统内的不同部分,提高性能。DLL(Delay Locked Loop)则用于精确的时钟相位控制。 6. **IOB**:IOB原语是FPGA与外部世界交互的关键,...

    xilinxFPGA资源调用原语

    在Xilinx FPGA设计中,原语(Primitive)是基本的逻辑构建块,它们代表了硬件电路的最基本元素。原语可以是逻辑门、触发器、计数器...在实际项目中,应根据具体需求,结合理论知识和实践经验,灵活运用原语来优化设计。

    xilinx原语

    在数字电路设计领域,Xilinx原语是至关重要的概念,特别是在使用Xilinx FPGA(Field-Programmable Gate Array)进行硬件描述语言(如VHDL或Verilog)设计时。原语是Xilinx公司提供的基本逻辑单元,它们是构建复杂...

Global site tag (gtag.js) - Google Analytics