无锁编程 / lock-free / 非阻塞同步

无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。
实现非阻塞同步的方案称为“无锁编程算法”( Non-blocking algorithm)。
lock-free是目前最常见的无锁编程的实现级别(一共三种级别)。

为什么要 Non-blocking sync ?

使用lock实现线程同步有很多缺点:
* 产生竞争时,线程被阻塞等待,无法做到线程实时响应。
* dead lock。
* live lock。
* 优先级翻转。
* 使用不当,造成性能下降。
 
如果在不使用 lock 的情况下,实现变量同步,那就会避免很多问题。虽然目前来看,无锁编程并不能替代 lock。

实现级别

非同步阻塞的实现可以分成三个级别:wait-free/lock-free/obstruction-free。
 
wait-free
是最理想的模式,整个操作保证每个线程在有限步骤下完成。
保证系统级吞吐(system-wide throughput)以及无线程饥饿。
截止2011年,没有多少具体的实现。即使实现了,也需要依赖于具体CPU。
 
lock-free
允许个别线程饥饿,但保证系统级吞吐。
确保至少有一个线程能够继续执行。
wait-free的算法必定也是lock-free的。
 
obstruction-free
在任何时间点,一个线程被隔离为一个事务进行执行(其他线程suspended),并且在有限步骤内完成。在执行过程中,一旦发现数据被修改(采用时间戳、版本号),则回滚。
也叫做乐观锁,即乐观并发控制(OOC)。事务的过程是:1读取,并写时间戳;2准备写入,版本校验;3校验通过则写入,校验不通过,则回滚。
lock-free必定是obstruction-free的。

CAS原语

LL/SC, atom read-modify-write
如果CPU提供了Load-Link/Store-Conditional(LL/SC)这对指令,则就可以轻松实现变量的CPU级别无锁同步。
LL [addr],dst:从内存[addr]处读取值到dst。
SC value,[addr]:对于当前线程,自从上次的LL动作后内存值没有改变,就更新成新值。
上述过程就是实现lock-free的 read-modify-write 的原子操作。
 
CAS (Compare-And-Swap)
LL/SC这对CPU指令没有实现,那么就需要寻找其他算法,比如CAS。
CAS是一组原语指令,用来实现多线程下的变量同步。
在 x86 下的指令CMPXCHG实现了CAS,前置LOCK既可以达到原子性操作。截止2013,大部分多核处理器均支持CAS。
CAS原语有三个参数,内存地址,期望值,新值。如果内存地址的值==期望值,表示该值未修改,此时可以修改成新值。否则表示修改失败,返回false,由用户决定后续操作。
Bool CAS(T* addr, T expected, T newValue)
{
if( *addr == expected )
{
*addr = newValue;
return true;
}
else
return false;
}
ABA 问题
thread1意图对val=1进行操作变成2,cas(*val,1,2)。
thread1先读取val=1;thread1被抢占(preempted),让thread2运行。
thread2 修改val=3,又修改回1。
thread1继续执行,发现期望值与“原值”(其实被修改过了)相同,完成CAS操作。
 
使用CAS会造成ABA问题,特别是在使用指针操作一些并发数据结构时。
 
解决方案
ABAʹ:添加额外的标记用来指示是否被修改。

语言实现

Java demo
AtomicInteger atom = new AtomicInteger(1);
boolean r = atom.compareAndSet(1, 2);
 
C# demo
int i=1;
Interlocked.Increment(ref i);
 
 
补充:ConcurrentLinkedQueue(循环CAS+volatile 实现的wait-free并发算法)

【多线程】无锁编程以及CAS的更多相关文章

  1. 4.锁--无锁编程以及CAS

    无锁编程以及CAS 无锁编程 / lock-free / 非堵塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被堵塞的情况下实现变量的同步,所以也叫非堵塞同步(Non-b ...

  2. 无锁编程以及CAS

    无锁编程 / lock-free / 非阻塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Sy ...

  3. [充电]多线程无锁编程--原子计数操作:__sync_fetch_and_add等12个操作

    转自:http://blog.csdn.net/minCrazy/article/details/40791795 多线程间计数操作.共享状态或者统计相关时间次数,这些都需要在多线程之间共享变量和修改 ...

  4. 无锁编程(四) - CAS与ABA问题

    CAS 一般采用原子级的read-modify-write原语来实现Lock-Free算法,其中LL和SC是Lock-Free理论研究领域的理想原语,但实现这些原语需要CPU指令的支持,非常遗憾的是目 ...

  5. Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。

    精彩理解:  https://www.jianshu.com/p/21be831e851e ;  https://blog.csdn.net/heyutao007/article/details/19 ...

  6. 【Java并发编程】2、无锁编程:lock-free原理;CAS;ABA问题

    转自:http://blog.csdn.net/kangroger/article/details/47867269 定义 无锁编程是指在不使用锁的情况下,在多线程环境下实现多变量的同步.即在没有线程 ...

  7. C++11原子操作与无锁编程(转)

    不讲语言特性,只从工程角度出发,个人觉得C++标准委员会在C++11中对多线程库的引入是有史以来做得最人道的一件事:今天我将就C++11多线程中的atomic原子操作展开讨论:比较互斥锁,自旋锁(sp ...

  8. C++性能榨汁机之无锁编程

    C++性能榨汁机之无锁编程 来源 http://irootlee.com/juicer_lock_free/ 前言 私以为个人的技术水平应该是一个螺旋式上升的过程:先从书本去了解一个大概,然后在实践中 ...

  9. [转]透过 Linux 内核看无锁编程

    非阻塞型同步 (Non-blocking Synchronization) 简介 如何正确有效的保护共享数据是编写并行程序必须面临的一个难题,通常的手段就是同步.同步可分为阻塞型同步(Blocking ...

随机推荐

  1. 02 spring security 自定义用户认证流程

    1. 自定义登录页面 (1)首先在static目录下面创建login.html       注意: springboot项目默认可以访问resources/resources, resources/s ...

  2. php strncasecmp()函数 语法

    php strncasecmp()函数 语法 作用:比较字符串前n个字符,不区分大小写直线电机 语法:strncasecmp(string1,string2,length) 参数: 参数 描述 str ...

  3. JS中数据结构之队列

    队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按 顺序排列的数据,先进先出. 队列的两种主要操作是:向队列中插入新元素和删除队列中的元素.插入操作也叫做入 队,删除操作也 ...

  4. 一、生成网络表--create Netlist

    Orcad Capture原理图篇 一.生成网络表--create Netlist 1.操作: .dsn文件--Tools--create Netlist 出现如下对话框--默认不进行更改--点击确定 ...

  5. 转载--关于FPGA设计数字信号处理电路的心得

    FPGA使用的越来越广泛,除了可用于设计控制电路以为,数字信号处理电路更是FPGA的强项和难点.个人可以说才刚刚入门FPGA设计,也做过一些数字信号处理方面的电路设计,记录下个人心得体会. (一)善用 ...

  6. 【Flutter学习】基本组件之弹窗和提示(SnackBar、BottomSheet、Dialog)

    一,概述 Flutter中的操作提示主要有这么几种 SnackBar.BottomSheet.Dialog,因为 Dialog样式比较多,放最后讲好了 二,介绍 SnackBar SnackBar的源 ...

  7. Python基础教程(013)--一行代码不要做多件事情

    前言 学习代码编写风格 内容 语法错误报错的信息 SystaxErrot:invalid syntax 语法错误, invalid 无效 每行代码负责完成一个动作 阅读代码,从左至右,从上到下. 学习 ...

  8. python魔法方法__reduce__()的妙用

    一.__reduce__()介绍 当定义扩展类型时(也就是使用Python的C语言API实现的类型),如果你想pickle它们,你必须告诉Python如何pickle它们. __reduce__ 被定 ...

  9. Spring中ApplicationContext加载机制和配置初始化

    Spring中ApplicationContext加载机制.        加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet.        ...

  10. <转>Excel生成guid、uuid

    Excel生成guid.uuid  原文地址:https://www.cnblogs.com/jory/p/7718305.html  1.Excel生成guid,uuid  格式:600d65bc- ...