非阻塞算法(non-blocking algorithms)定义
 
     所谓非阻塞算法是相对于锁机制而言的,是指:一个线程的失败或挂起不应该引起另一个线程的失败或挂起的一种算法。一般是利用硬件层面支持的原子化操作指令来取代锁的,比如CAS(compare and swap),从而保证共享数据在并发访问下的数据一致性。
 
由AtomicInteger的线程安全机制说起
 
AtomicInteger内部是如何保证线程同步的呢?我们先看AtomicInteger内部的一个典型的方法:
     public final int getAndSet(int newValue) {
        for (;;) {
            int current = get();
            if (compareAndSet(current, newValue))
                return current;
        }
   }
     public final boolean compareAndSet (int expect, int update) {
       return unsafe.compareAndSwapInt(thisvalueOffset, expect, update);
   }
 
解释:compareAndSet方法内部是调用Java本地方法compareAndSwapInt来实现的,而compareAndSwapInt方法内部又是借助C来调用CPU的底层指令来保证在硬件层面上实现原子操作的。在intel处理器中,CAS是通过调用cmpxchg指令完成的。这就是我们常说的CAS操作(compare and swap)。CAS操作很容易理解,一般来说有三个值:内存值V,期望值A,更新值B,如果内存值V和期望值A相等,那么就用更新值B替换内存值,否则什么都不做。想象一下,假设AtomicInteger当前的value值为1,某个线程A正在执行上述的getAndSet方法,当执行到compareAndSet方法的时候,被另一个线程B抢占了,线程B成功将内存值更新为2,然后轮到线程A来继续执行上述还没有执行完的比较并更新操作,由于线程A上次获得到的current值是1,然后开始执行compareAndSet方法(最后交由CPU的原子执行来执行的),comareAndSet方法发现当前内存值V=2,而期望值A=1(current变量值),所以就不会产生值交换,然后继续下一次重试,在没有别的线程抢占的情况下,下一个循环(在并发很高的情况下可能经过更多次的循环)线程A就能够设置成功,如果线程A是在还没有运行int current = get()这一行操作时被抢占了,那么线程B运行完毕后,线程A获得的将是线程B修改后的值然后进行CAS操作可能就一次成功(在没有其他线程抢占的情况下)。因此,CAS Try-Loop操作能够很好的提供线程同步机制,我们又将此实现过程称之为线程同步的无阻塞算法,又叫”CAS循环”,”lock-free“或”wait-free“算法。
 
非阻塞算法的优点
 
  在java5.0版本时,我们只能通过synchronized来实现线程的同步,synchronized是一种独占锁,独占锁是一种悲观锁,当一个线程访问共享资源的时候,其他线程必须处在阻塞状态,只有在拥有锁的线程释放锁以后才能被其他线程锁竞争,JVM 实现阻塞的方式通常是挂起阻塞的线程,过一会儿再重新调度它。由此造成的上下文切换相对于锁保护的少数几条指令来说,会造成相当大的延迟,这将引起性能问题,所以我们称这种锁为重量级锁。所谓乐观锁就是指:对竞争资源不用加锁,而是假设没有冲突去完成某项操作,如果因为冲突失败就不断重试,直到成功为止。上面所说的循环CAS操作就是上述所说的乐观锁。
  1. 利用硬件的原生支持代替JVM对代码路径的锁定,从而提供更细粒度(独立的内存地址)的同步。
  2. 失败的线程可以立即重试而不用被挂起,降低了争用成本,即使有少量失败的CAS操作,也依然锁争用造成的重新调度快的多
  3. 争用CAS提供更短的延迟(因为争用CAS比争用锁会更快),提供更好的吞吐率。
  4. 对生存问题(死锁和线程优先级反转)提供更好的防御
在轻度到中度的争用情况下阻塞算法的性能会超越阻塞算法,因为 CAS 的多数时间都在第一次尝试时就成功,而发生争用时的开销也不涉及线程挂起和上下文切换,只多了几个循环迭代。没有争用的 CAS 要比没有争用的锁便宜得多(这句话肯定是真的,因为没有争用的锁涉及 CAS 加上额外的处理),而争用的 CAS 比争用的锁获取涉及更短的延迟。在高度争用的情况下(即有多个线程不断争用一个内存位置的时候),基于锁的算法开始提供比非阻塞算法更好的吞吐率,因为当线程阻塞时,它就会停止争用,耐心地等候轮到自己,从而避免了进一步争用。但是,这么高的争用程度并不常见,因为多数时候,线程会把线程本地的计算与争用共享数据的操作分开,从而给其他线程使用共享数据的机会。
 
参考:

基于CAS操作的非阻塞算法的更多相关文章

  1. Java锁与非阻塞算法的性能比较与分析+原子变量类的应用

    15.原子变量与非阻塞同步机制 在java.util.concurrent包中的许多类,比如Semaphore和ConcurrentLinkedQueue,都提供了比使用Synchronized更好的 ...

  2. 《java并发编程实战》读书笔记12--原子变量,非阻塞算法,CAS

    第15章 原子变量与非阻塞同步机制 近年来,在并发算法领域的大多数研究都侧重于非阻塞算法,这种算法用底层的原子机器指令(例如比较并交换指令)代替锁老确保数据在并发访问中的一致性. 15.1 锁的劣势 ...

  3. Java 理论与实践: 非阻塞算法简介——看吧,没有锁定!(转载)

    简介: Java™ 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,java.util.concurrent 包充分地利用了这个功能.非阻塞算法属于并发算法,它们可以安全地派生它们的线程, ...

  4. Java 理论与实践: 非阻塞算法简介--转载

    在不只一个线程访问一个互斥的变量时,所有线程都必须使用同步,否则就可能会发生一些非常糟糕的事情.Java 语言中主要的同步手段就是synchronized 关键字(也称为内在锁),它强制实行互斥,确保 ...

  5. java并发之非阻塞算法介绍

    在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的. 为了更好的理解阻塞算 ...

  6. 29、Java并发性和多线程-非阻塞算法

    以下内容转自http://ifeve.com/non-blocking-algorithms/: 在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在 ...

  7. Java 理论与实践-非阻塞算法简介

    在不只一个线程访问一个互斥的变量时,所有线程都必须使用同步,否则就可能会发生一些非常糟糕的事情.Java 语言中主要的同步手段就是 synchronized 关键字(也称为内在锁),它强制实行互斥,确 ...

  8. 非阻塞算法(Lock-Free)的实现

    目录 非阻塞的栈 非阻塞的链表 非阻塞算法(Lock-Free)的实现 上篇文章我们讲到了使用锁会带来的各种缺点,本文将会讲解如何使用非阻塞算法.非阻塞算法一般会使用CAS来协调线程的操作. 虽然非阻 ...

  9. 《Java并发编程实战》笔记-非阻塞算法

    如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败和挂起,那么这种算法就被称为非阻塞算法.如果在算法的每个步骤中都存在某个线程能够执行下去,那么这种算法也被称为无锁(Lock-Free)算法 ...

随机推荐

  1. Cygwin工具的简单使用

    简介 从使用角度来看:Cygwin就是一个windows软件,该软件就是在windows上仿真linux操作系统.简言之,cygwin是一个在windows平台上运行的 linux模拟环境,使用一个D ...

  2. Part 3 - Advanced Concepts(11-13)

    https://simpleisbetterthancomplex.com/series/2017/09/18/a-complete-beginners-guide-to-django-part-3. ...

  3. ubuntu16.4中开启vncserver进行远程桌面

    使用x11vnc作为vncserver端 1 安装x11vnc $ sudo apt-get update $ sudo apt-get install x11vnc 2 生成密码 $ x11vnc ...

  4. Exception in thread Thread-3:第三个线程意外

    Status:Executing -train.py 02/09/2019 09:33:38 INFO Log level set to: INFO Using TensorFlow backend. ...

  5. AQS详解(AbstractQueuedSynchronizer)

    Intrinsic VS explicity 1. 不一定保证公平              1. 提供公平和非公平的选择 2. 无                          2. 提供超时的 ...

  6. c++中sort()及qsort()的用法总结

    当并算法详解请见点我 想起来自己天天排序排序,冒泡啊,二分查找啊,结果在STL中就自带了排序函数sort,qsort,总算把自己解脱了~ 所以自己总结了一下,首先看sort函数见下表: 函数名 功能描 ...

  7. cordova3.X-4.0添加自定义插件方法

    cordova3.X之后,插件不能自己手动添加了,手动添加后,只要cordova build,数据立即被抹去. 因此,3.X后要添加插件,需要用 cordova plungin add "你 ...

  8. Android-DateUtil工具类

    时间相关工具类 public class DateUtil { private DateUtil(){} /** * 枚举日期格式 */ public enum DatePattern{ /** * ...

  9. 使用回调方式写POI导入excel工具类

    场景是这样的:为了做一个excel导入的功能,为了尽可能的写一个通用的工具类,将与poi有关的东西都封装起来,以便以其他人员只用关心自己的业务,不用和poi打交道. 写到最后,现在还是会有poi的东西 ...

  10. Linq to Object 的简单使用示例

    语言集成查询 (LINQ) 是 Visual Studio 2008 中引入的一组功能,可为 C# 和 Visual Basic 语言语法提供强大的查询功能. LINQ 引入了标准易学的数据查询和更新 ...