一、非阻塞同步(Non-blocking Synchronization)

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

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

实现非阻塞同步的方案称为“无锁编程算法”( Non-blocking algorithm)。

lock-free是目前最常见的无锁编程的实现级别(一共三种级别):

  • wait-free
  • lock-free
  • obstruction-free

2. 为什么要 Non-blocking sync ?

使用lock实现线程同步有很多缺点:

* 产生竞争时,线程被阻塞等待,无法做到线程实时响应。

* dead lock。

* live lock。

* 优先级翻转。

* 使用不当,造成性能下降。

3. wait-free

是最理想的模式,整个操作保证每个线程在有限步骤下完成。

保证系统级吞吐(system-wide throughput)以及无线程饥饿。

截止2011年,没有多少具体的实现。即使实现了,也需要依赖于具体CPU。

4. lock-free

允许个别线程饥饿,但保证系统级吞吐。

确保至少有一个线程能够继续执行。

wait-free的算法必定也是lock-free的。

5. obstruction-free

在任何时间点,一个线程被隔离为一个事务进行执行(其他线程suspended),并且在有限步骤内完成。

在执行过程中,一旦发现数据被修改(采用时间戳、版本号),则回滚。

也叫做乐观锁,即乐观并发控制(OOC)。

事务的过程是:1读取,并写时间戳;2准备写入,版本校验;3校验通过则写入,校验不通过,则回滚。

二、CAS

CAS( compare and swap) 原子操作,用来实现多线程下的变量同步。

保证了如果需要更新的地址没有被其他进程(线程)改动过,那么它可以安全的写入。

而这也是我们对于某个数据或者数据结构加锁要保护的内容,保证读写的一致性,不出现dirty data。

CAS原语有三个参数:

  • 内存地址,
  • 期望值,
  • 新值。

算法逻辑:

  • 如果内存地址的值==期望值,表示该值未修改,此时可以修改成新值。
  • 否则表示修改失败,返回false,由用户决定后续操作。
int compare_and_swap (int* reg, int oldval, int newval) {
ATOMIC();
int old_reg_val = *reg;
if (old_reg_val == oldval)
*reg = newval;
END_ATOMIC();
return old_reg_val;
}

可在循环中不断执行CAS,如果共享变量没有改变,那么swap,在当前环境中写入,否则继续do-while的Retry-Loop。

三、ABA问题

ABA问题最容易发生在lock free算法中的,地址被重用的情况。

无锁相当于“锁”的粒度变小了,主要是“锁”HEAD和TAIL这两个关键资源。而不是整个数据结构。

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);

lock free(无锁并发)是什么的更多相关文章

  1. Lock Free (无锁并发)

    CAS( compare and swap) 原子操作,保证了如果需要更新的地址没有被其他进程(线程)改动过,那么它可以安全的写入.而这也是我们对于某个数据或者数据结构加锁要保护的内容,保证读写的一致 ...

  2. 无锁并发框架Disruptor学习入门

    刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...

  3. 加锁并发算法 vs 无锁并发算法

    Heinz Kabutz 在上周举办了一次成功 JCrete研讨会,我在会上参加了对一种新的 StampedLock(于JSR166中 引入) 进行的评审.StampedLock (邮戳锁) 旨在解决 ...

  4. Nah Lock: 一个无锁的内存分配器

    概述 我实现了两个完全无锁的内存分配器:_nalloc 和 nalloc.  我用benchmark工具对它们进行了一组综合性测试,并比较了它们的指标值. 与libc(glibc malloc)相比, ...

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

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

  6. 使用CAS实现无锁的SkipList

    无锁 并发环境下最常用的同步手段是互斥锁和读写锁,例如pthread_mutex和pthread_readwrite_lock,常用的范式为: void ConcurrencyOperation() ...

  7. linux内核无锁缓冲队列kfifo原理

    Linux kernel里面从来就不缺少简洁,优雅和高效的代码 比如,通过限定写入的数据不能溢出和内存屏障实现在单线程写单线程读的情况下不使用锁.因为锁是使用在共享资源可能存在冲突的情况下.还用设置b ...

  8. 海量并发的无锁编程 (lock free programming)

    最近在做在线架构的实现,在线架构和离线架构近线架构最大的区别是服务质量(SLA,Service Level Agreement,SLA 99.99代表10K的请求最多一次失败或者超时)和延时.而离线架 ...

  9. 基于无锁的C#并发队列实现(转载)

    最近开始学习无锁编程,和传统的基于Lock的算法相比,无锁编程具有其独特的优点,Angel Lucifer的关于无锁编程一文对此有详细的描述. 无锁编程的目标是在不使用Lock的前提下保证并发过程中共 ...

随机推荐

  1. P95、P99.9百分位数值——服务响应时间的重要衡量指标

    前段时间,在对系统进行改版后,经常会有用户投诉说页面响应较慢,我们看了看监控数据,发现从接口响应时间的平均值来看在500ms左右,也算符合要求,不至于像用户说的那么慢,岁很费解,后来观察其它的一些指标 ...

  2. 【DB宝36】使用Docker分分钟搭建漂亮的prometheus+grafana监控

    目录 一.部署Prometheus+grafana环境 1.1.下载Prometheus+grafana镜像 1.2.创建镜像 1.3.浏览器访问 二.监控Linux主机 2.1.在被监控主机上部署n ...

  3. HTTP1.0/1.1/2.0

    https://www.cnblogs.com/heluan/p/8620312.html http缓存策略 https://www.cnblogs.com/Iwillknow/archive/201 ...

  4. springmvc框架java.lang.NoSuchMethodException问题解决

    例子:https://blog.csdn.net/huaidandaidai1/article/details/81979704 原因: 在java中,如果一个类A没有自己写构造方法,那么java会自 ...

  5. Vue3(三)CND + ES6的import + 工程化的目录结构 = 啥?

    突发奇想 这几天整理了一下vue的几种使用方式,对比之后发现有很多相似之处,那么是不是可以混合使用呢?比如这样: vue的全家桶和UI库,采用传统的方式加载(CND.script). 自己写的js代码 ...

  6. 用java实现word转pdf

    摘要:如何用java实现word文档转pdf呢 最近在网上看了很多资料,遇到了很多头疼的问题,看了各类大神写的方法,最初想要研究的是在线预览word 现在来看,不太现实,除了微软研究的一套在线预览的u ...

  7. spark SQL (一)初识 ,简介

    一, 简介 Spark SQL是用于结构化数据处理的Spark模块.与基本的Spark RDD API不同,Spark SQL提供的接口为Spark提供了关于数据结构和正在执行的计算的更多信息.在内部 ...

  8. js创建javaMap

    /** * Simple Map * var m = new Map(); * m.put('key','value'); * var v_otherMap = v_m.toMapString();* ...

  9. 6. Linux输入输出重定向

    1.输入重定向是指把文件导入到命令中,而输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中. 输入重定向中用到的符号及其作用 输出重定向中用到的符号及其作用 1)通过输出重定向将原本要输出到 ...

  10. A - The Suspects (sars传染)

    题意:有m组,0为起点,有0的那一组全是嫌疑人,之后会不断传递到其它组去,问一共有多少人是嫌疑人. Severe acute respiratory syndrome (SARS), an atypi ...