并发之原子变量与CAS 算法

当程序更新一个变量的时候,如果多线程同时更新这个变量,可能得到期望之外的值,我们在jmm内存模型中https://www.jianshu.com/writer#/notebooks/40095376/notes/65884552提到的volatile,解决内存可见性以及禁止指令重排序,但是解决不了线程安全问题,通常我们会用synchronized解决,悲观锁保证了线程不会同时更新,可能会造成线程阻塞,CAS算法也就是Compare and swap(比较交换)是一种乐观锁,原子操作类运用的CAS算法解决线程变量的不安全问题,简单性能高效的更新变量的方式。

CAS算法的核心是:读取原先的值V,预估现在的值A,即将更新的值B,如果V等于A那么就将B更新,否则不进行更新。

在jdk 1.5 引进了并发工具包concurrent,其中有一个包名为atomic的包,包含了几种常用的原子类

jdk 1.8并发工具包的原子类

从上图我们可以看到atomic包中包含的类:原子更新布尔类型,原子更新整型,原子更新长整型。原子更新整型数组,原子更新长整型数组,原子更新引用类型数组,原子更新饮用类型,原子更新引用类型里面的字段(含field的类),原子更新都有标记位的引用类。主要包含的这些,大体可以根据英文名字对应上。并且像原子更新布尔,整型,和长整型使用上都一样,数组这款也一样的核心,引用类型的更新我们一会看一个例子,同样的核心方法我们就举例的时候只举一类。

我们知道一个i++操作底层分为三步:将i读取出来放入临时变量,对i的值进行加1更改,然后最后一步就是将临时变量赋值给i。

10个线程同时执行的时候产生了问题

当然我们用synchronized可以解决以上问题,那么我们今天用AtomicInteger这个类


AtomicInteger的使用


AtomicIntegerArray使用

这里面有一个方法ai.getAndSet(0,3),如果把第12行去掉大家看下13行应该打印什么?答案是1,打印的原先的值,在声明ai的时候是将value中的数据copy进ai中去的,所以应该打印原先的1。


AtomicReference的使用

AtomicReference原子引用类可改变引用对象的值。

AtomicIntegerFieldUpdaterd的使用

AtomicIntegerFieldUpdater改变指定对象的某个值,但是这个指定要改变的对象的字段需要加上volatile才可以使用,也就是old 这个字段需要加上volatile,保证线程的可见性。因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()创建一个更新期,并且需要设置想要更新的类和属性。

1)在上述的例子中,对于字段old的修改,其中old的修饰必须是基本类型数据,用volatile修饰,不能是包装类型,int,long就可以,但是不可以是Integer和Long;2) 必须是实例变量,不可以是类变量;3) 必须是可变的变量,不能是final修饰的变量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一.线程安全性 线程安全是建立在对于对象状态访问操作进行管理,特别是对共享的与可变的状态的访问 解释下上面的话: ...
    黄大大吃不胖阅读 960评论 0 3
  • 所有知识点已整理成app app下载地址 J2EE 部分: 1.Switch能否用string做参数? 在 Jav...
    侯蛋蛋_阅读 2,710评论 1 4
  • 第2章 java并发机制的底层实现原理 Java中所使用的并发机制依赖于JVM的实现和CPU的指令。 2.1 vo...
    kennethan阅读 1,533评论 0 2
  • 09-享受呼吸-《六祖坛经》第三品决疑品之读后感170804 ——决疑品读后,领悟到佛法并非生活之外的教法,它实际...
    尔慷阅读 1,357评论 0 2
  • 过完年,鼻子就不太通气,一个多月了,一直这样,我意识到这是病,得治。别人忽视了男人的健康,男人,请不要欺骗自己。关...
    太阳石阅读 270评论 0 3

友情链接更多精彩内容