无锁编程以及CAS

无锁编程 / 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);
 

Refs

4.锁--无锁编程以及CAS的更多相关文章

  1. java多线程中的死锁、活锁、饥饿、无锁都是什么鬼?

    死锁.活锁.饥饿是关于多线程是否活跃出现的运行阻塞障碍问题,如果线程出现了这三种情况,即线程不再活跃,不能再正常地执行下去了. 死锁 死锁是多线程中最差的一种情况,多个线程相互占用对方的资源的锁,而又 ...

  2. Java的死锁及解决思路(延伸: 活锁,饥饿,无锁)

    死锁: A线程持有 锁1,接下来要获取锁2:与此同时,B线程持有锁2,要获取锁1.两个线程都在等对方释放自己需要的锁,这时两方会永远等待下去,就形成了死锁. 死锁的四个必要条件: 1.互斥:资源(锁) ...

  3. 无锁编程以及CAS

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

  4. 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法

    转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...

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

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

  6. 【多线程】无锁编程以及CAS

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

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

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

  8. 非阻塞同步算法与CAS(Compare and Swap)无锁算法

    锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...

  9. paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象)

    paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象) 1     锁的缺点 2     CAS(Compare ...

随机推荐

  1. Swift - 异步加载各网站的favicon图标,并在单元格中显示

    下面是一个简单的应用,表格视图的各个单元格自动异步加载各个网站的favicon图标,并显示出来. 主要是复习下如何自定义单元格,单元格中图片的异步加载,以及didSet的用法. 效果图如下: 操作步骤 ...

  2. BZOJ 2705: [SDOI2012]Longge的问题( 数论 )

    T了一版....是因为我找质因数的姿势不对... 考虑n的每个因数对答案的贡献. 答案就是 ∑ d * phi(n / d) (d | n) 直接枚举n的因数然后求phi就行了. 但是我们可以做的更好 ...

  3. Dynamic Pivot table wizard SQL Server

    原文 http://www.gyurcit.hu/pivot.html Dynamic Pivot table wizard This stored procedure generate dynami ...

  4. inner join、left join、right join中where和and的作用

    inner join.left join.right join中where和and的作用 .内连接(自然连接): 只有两个表相匹配的行才能在结果集中出现 2.外连接: 包括  (1)左外连接 (左边的 ...

  5. /bin/bash^M: 坏的解释器: 没有那个文件或目录

    在Linux下编译cocos2d-x运行脚本的时候出现”/bin/bash^M: 坏的解释器: 没有那个文件或目录“这样的错误如下图. 解决方法: 使用在终端输入sed -i 's/\r$//' ma ...

  6. Android ble 蓝牙4.0 总结

    本文介绍Android ble 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用,如果手机系统版本API level < 18,也是用不了蓝牙4.0的哦 ...

  7. HTML5 Canvas自定义圆角矩形与虚线(Rounded Rectangle and Dash Line)

    HTML5 Canvas自定义圆角矩形与虚线(RoundedRectangle and Dash Line) 实现向HTML Canvas 2d context绘制对象中添加自定义的函数功能演示,如何 ...

  8. Socket开发时,Available为0,实际还有数据的问题

    这段时间处理Socket通讯,比如文件传输,通常代码如下: string filename = @"c:\abc.txt"; // 发送文件名字符串长度(测试代码,实际请传输字符串 ...

  9. 基于visual Studio2013解决C语言竞赛题之1088模拟计算器

        题目 解决代码及点评 /************************************************************************/ /* ...

  10. mui如何增加自定义字体icon图标

    http://ask.dcloud.net.cn/article/128 字体地址:http://www.iconfont.cn/