具体CAS操作

上一篇讲述了CAS机制,这篇讲解CAS具体操作.

什么是悲观锁、乐观锁?在java语言里,总有一些名词看语义跟本不明白是啥玩意儿,也就总有部分面试官拿着这样的词来忽悠面试者,以此来找优越感,其实理解清楚了,这些词也就唬不住人了。

  • synchronized是悲观锁,这种线程一旦得到锁,其他需要锁的线程就挂起的情况就是悲观锁。

  • CAS操作的就是乐观锁,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

那么问题来了,什么是CAS操作?

CAS是Compare-and-swap(比较与替换)的简写,是一种有名的无锁算法,在java中,我们主要分析Unsafe类,因为所有的CAS操作都是它来实现的,而在Unsafe类中这些方法也都是native方法

    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

  public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

  public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

看到上面的解释是不是索然无味,查找了很多资料也没完全弄明白,通过几次验证后,终于明白,最终可以理解成一个无阻塞多线程争抢资源的模型。先上代码

package com.company.reentrantLock;

import java.util.concurrent.atomic.AtomicBoolean; public class AtomicBooleanTest implements Runnable{
  public static AtomicBoolean exits = new AtomicBoolean(true);
  public static void main(String[] args) {
      AtomicBooleanTest abd = new AtomicBooleanTest();
      Thread t1 = new Thread(abd);
      Thread t2 = new Thread(abd);
      t1.start();
      t2.start();
  }

  @Override
  public void run() {
      System.out.println("begin run");
      System.out.println("real " + exits.get());
      if(exits.compareAndSet(true,false)){
          System.out.println(Thread.currentThread().getName() + " " + exits.get() );
          exits.set(true);
      }else{
          run();
      }
  }
}

输出结果:

begin run
real true
Thread-1 false
begin run
real true
Thread-0 false

这里无论怎么运行,Thread-1、Thread-0都会执行if=true条件,而且还不会产生线程脏读脏写,这是如何做到的了,这就用到了我们的compareAndSet(boolean expect,boolean update)方法,先上图简单讲解下程序原理,然后再分析compareAndSet作用。

这个图中重最要的是compareAndSet(true,false)方法要拆开成compare(true)方法和Set(false)方法理解,是compare(true)是等于true后,就马上设置共享内存为false,这个时候,其它线程无论怎么走都无法走到只有得到共享内存为true时的程序隔离方法区。 但是这种得不到状态为true时使用递归算法是很耗cpu资源的,所以一般情况下,都会有线程sleep。

总结

这篇文章并没有展开讲compareAndSet底层调用的是unsafe.compareAndSwapInt方法,因为这是native方法,很多人都会展开找源码,最后也只找到是调用CPU方法,没讲到具体用法,如果只用compareAndSet(true,false)举例则更加简单。 这种无阻塞式的多线程操作数据,在大并发情况下,是一笔非常可观的性能提升,所以,如果在大并发或多线程性能要求高的情况下有更加好的技术选型,可以参考这种底层实现。

结合JMM知识,线程间共享的变量,首先在主存中会保留一份,然后每个线程的工作内存也会保留一份副本.

我们对比发现,这里的预期值就是线程保留的副本,当该线程从主存中获取该变量值后,主存中该变量可能已经被其他线程刷新了,但是该线程工作内存中该变量却还是原来的值,这就是所谓的预期值.

当你要CAS刷新该值的时候,如果发现线程工作内存和主存中不一致,就会失败.如果一致,就可以更新成功

具体CAS操作实现(无锁算法)的更多相关文章

  1. 锁、CAS操作和无锁队列的实现

    https://blog.csdn.net/yishizuofei/article/details/78353722 锁的机制 锁和人很像,有的人乐观,总会想到好的一方面,所以只要越努力,就会越幸运: ...

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

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

  3. CAS无锁算法与ConcurrentLinkedQueue

    CAS:Compare and Swap 比较并交换 java.util.concurrent包完全建立在CAS之上的,没有CAS就没有并发包.并发包借助了CAS无锁算法实现了区别于synchroni ...

  4. 无锁算法CAS 概述

    无锁算法CAS 概述 JDK5.0以后的版本都引入了高级并发特性,大多数的特性在java.util.concurrent包中,是专门用于多线并发编程的,充分利用了现代多处理器和多核心系统的功能以编写大 ...

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

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

  6. java并发:AtomicInteger 以及CAS无锁算法【转载】

    1 AtomicInteger解析 众所周知,在多线程并发的情况下,对于成员变量,可能是线程不安全的: 一个很简单的例子,假设我存在两个线程,让一个整数自增1000次,那么最终的值应该是1000:但是 ...

  7. CAS(Compare and Swap)无锁算法-学习笔记

    非阻塞同步算法与CAS(Compare and Swap)无锁算法 这篇问题对java的CAS讲的非常透彻! 锁的代价 1. 内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的 ...

  8. CAS原子操作实现无锁及性能分析

    CAS原子操作实现无锁及性能分析 Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn.net/chen19870707 ...

  9. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

随机推荐

  1. Html5与Css3知识点拾遗(七)

    布局 实例:规范的命名和编排 <body> <div class="page"><!--page开始--> <header class=& ...

  2. Git学习篇之git remote add origin错误

    提示出错信息:fatal: remote origin already exists. 解决办法如下: 1.先输入$ git remote rm origin 2.再输入$ git remote ad ...

  3. bootstrap的化妆页面

    Glyphicons 字体图标 所有可用的图标 包括260个来自 Glyphicon Halflings 的字体图标.Glyphi cons Halflings 一般是收费的,但是他们的作者允许 Bo ...

  4. [Project] SpellCorrect源码详解

    该Project原来的应用场景是对电商网站中输入一个错误的商品名称进行智能纠错,比如iphoae纠错为iphone.以下介绍的这个版本对其作了简化,项目源代码地址参见我的github:https:// ...

  5. Android数据存储之SharedPreferences使用

    SharedPreferences是Android中一种轻型的数据存储类.本质上是基于XML文件进行存储Key-Value键值对的数据,生成的XML文件的目录在/data/data/包名/Shared ...

  6. a标签嵌套a标签在实际项目开发中遇到的坑

    大家都知道HTML的嵌套规范,其中一个规范是块元素嵌套行内元素,块元素嵌套块元素,行内元素嵌套行内元素,行内元素不能嵌套块元素. 其中需要注意的是行内元素嵌套行内元素,a标签虽然是行内元素,但是a标签 ...

  7. 动态页面技术EL

    1.EL概述: EL表达式可以嵌入再JSP页面内部,减少JSP脚本的编写 EL出现的目的是要替代JSP页面中脚本的编写 EL最重要的作用就是从域中取出数据: 引入: JSP中<%=request ...

  8. Git 常用命令备份

    继上次保存了git 多个key共存配置(https://www.cnblogs.com/xiaochangwei/p/9155195.html)后,今天把常见的git命令备份下(最近我的云笔记账号经常 ...

  9. python中stack在实际中的简单应用之进制转换

    计算机的世界是二进制的,而人类的世界是十进制的,当数学公式用计算机表达时,经常 要转换.这就用到了进制的转换. 首先,我们先了解一下二进制和十进制的发展历史: 二进制: 现代的二进制首先由大数学家莱布 ...

  10. 物体检测,Error: maximum box coordinate value is too large

    使用ssd目标检测,出现error:maximum box coordinate value is larger than 1.100000: ] [1.325] 主要原因在于,用labelImg 标 ...