接上一篇博客并发编程-多线程共享变量不安全,分析Atomic原子类是怎么保证线程安全的。

并发三个基本概念:

1.原子性:操作是线程私有的,不能拆分成多个步骤,被其他线程影响;(官方版:操作不可中断,全部执行或全部失败)

2.可见性:对共享变量的修改能够被其他线程可见;

3.有序性:cpu会为了优化对指令进行重排序,有序性保证线程内指令顺序一致。

看AtomicInteger的incrementAndGet方法如何保证原子性的。以下代码是CAS的过程:

public final int incrementAndGet() {for (;;) {int current = get(); //从主内存中拷贝value放到本地线程栈内存中 这二行代码可能另一个线程也在执行int next = current + 1; //做增加操作if (compareAndSet(current, next)) return next;}}
//调用unsafe的compareAndSwapInt方法
public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}public final int get() {return value;}private volatile int value;  //volatile保证了可见性,在incrementAndGet()方法中get()方法获取的value是从主内存中拿到的
private static final Unsafe unsafe = Unsafe.getUnsafe(); 

private static final long valueOffset;static {        try {         valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); //获取value值在AtomicInteger内存地址中的偏移量
        }catch (Exception ex)         { throw new Error(ex); } } 

//Unsafe class 代码 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

原理就是:线程A从主存中拿到value值,对value值做+1操作赋给newValue,然后再获取一次主内存的值,比较value和原值是否相等,如果相等,证明这个值没有被别的线程改变,对它设置新的值,如果不相等,证明这个值被别的线程更改了,重新获取一次,再次比较,直到相等、设置新值,返回新值。

再来看一下compareAndSwapInt方法 unsafe.cpp,(http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe.cpp):

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))UnsafeWrapper("Unsafe_CompareAndSwapInt");oop p = JNIHandles::resolve(obj);jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

主要实现Atomic::cmpxchg(x, addr, e)  继续看Atomic::cmpxchg , 这个本地方法的最终实现在openjdk的如下位置:

openjdk-7-fcs-src-b147-27jun2011\openjdk\hotspot\src\oscpu\windowsx86\vm\atomicwindowsx86.inline.hpp(对应于windows操作系统,X86处理器)
// Adding a lock prefix to an instruction on MP machine
// VC++ doesn't like the lock prefix to be on a single line
// so we can't insert a label after the lock prefix.
// By emitting a lock prefix, we can define a label after it.
#define LOCK_IF_MP(mp) __asm cmp mp, 0  \__asm je L0      \__asm _emit 0xF0 \__asm L0:inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {// alternative for InterlockedCompareExchangeint mp = os::is_MP();  //判断当前系统环境__asm {mov edx, dest   mov ecx, exchange_valuemov eax, compare_valueLOCK_IF_MP(mp)cmpxchg dword ptr [edx], ecx}
}

LOCK_IF_MP指的是如果是在多核环境时,cpu会加上lock,如果是单核环境,不会加lock,因此实际上也是通过lock在cpu层面加上了屏障,排他锁。但是cpu层面的锁比jvm层的sync锁效率要高很多。
 

转载于:https://www.cnblogs.com/zhengwangzw/p/9363654.html

并发编程-Atomic的compareAndSet相关推荐

  1. Java并发编程—Atomic原子类

    目录 Atomic 1. AtomicInteger a. 多线程并发访问问题 b. 用 AtomicInteger 类解决 2. AtomicIntegerArray a. 多线程并发访问问题 b. ...

  2. Java并发编程,无锁CAS与Unsafe类及其并发包Atomic

    为什么80%的码农都做不了架构师?>>>    我们曾经详谈过有锁并发的典型代表synchronized关键字,通过该关键字可以控制并发执行过程中有且只有一个线程可以访问共享资源,其 ...

  3. 并发编程-04线程安全性之原子性Atomic包的4种类型详解

    文章目录 线程安全性文章索引 脑图 概述 原子更新基本类型 Demo AtomicBoolean 场景举例 原子更新数组 Demo 原子更新引用类型 Demo 原子更新字段类型 使用注意事项: Dem ...

  4. 并发编程-03线程安全性之原子性(Atomic包)及原理分析

    文章目录 线程安全性文章索引 脑图 线程安全性的定义 线程安全性的体现 原子性 使用AtomicInteger改造线程不安全的变量 incrementAndGet源码分析-UnSafe类 compar ...

  5. atomic原子类实现机制_并发编程:并发操作原子类Atomic以及CAS的ABA问题

    本文基于JDK1.8 Atomic原子类 原子类是具有原子操作特征的类. 原子类存在于java.util.concurrent.atmic包下. 根据操作的数据类型,原子类可以分为以下几类. 基本类型 ...

  6. 面试准备每日系列:计算机底层之并发编程(一)原子性、atomic、CAS、ABA、可见性、有序性、指令重排、volatile、内存屏障、缓存一致性、四核八线程

    文章目录 1. 什么是进程?什么是线程? 2. 线程切换 3. 四核八线程是什么意思 3.1 单核CPU设定多线程是否有意义 4. 并发编程的原子性 4.1 如何解决原子性问题 & atomi ...

  7. Java并发编程-无锁CAS与Unsafe类及其并发包Atomic

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772470 出自[zejian ...

  8. Java并发编程包中atomic的实现原理

    转载自   Java并发编程包中atomic的实现原理 这是一篇来自粉丝的投稿,作者[林湾村龙猫]最近在阅读Java源码,这一篇是他关于并发包中atomic类的源码阅读的总结.Hollis做了一点点修 ...

  9. 「死磕Java并发编程」说说Java Atomic 原子类的实现原理

    <死磕 Java 并发编程>系列连载中,大家可以关注一波. 「死磕 Java 并发编程」阿里二面,面试官:说说 Java CAS 原理? 「死磕 Java 并发编程」面试官:说说什么是 J ...

最新文章

  1. orcale 日期转字符串 去掉0_C# 基础知识系列- 13 常见类库介绍(二)日期时间类...
  2. tflearn 在每一个epoch完毕保存模型
  3. 我来做百科(第六天)
  4. directx 9.27.1734 多语言完整版 下载
  5. table类型数据提交_OGG数据同步异常问题总结
  6. Windows系统环境下Solr之Java实战(三)使用solrJ管理索引库
  7. 惊现飞鸽传书2009
  8. toj 4597 字符识别?
  9. 【j2ee spring】30、巴巴荆楚网-综合hibernate4+spring4(5)分页
  10. 纵坐标范围_探索频率范围与频响的奥秘
  11. transformers model inputs
  12. jmeter分布式性能测试
  13. 阿里python400集_自学成才的阿里大牛整理的400集自用Python视频资料,万物皆可爬...
  14. 【三维路径规划】基于matlab RRT算法无人机三维路径规划【含Matlab源码 1363期】
  15. 522. 最长特殊序列 II
  16. linux 自动ping脚本,ping自动报警shell脚本forlinux
  17. 移动通信网络演进之路
  18. 词法分析器(不讲武德java版)
  19. JS 导出excel文件流
  20. 《终身成长》读书分享(附思维导图)

热门文章

  1. [CodePlus 2017 11月赛]晨跑 题解(辗转相除法求GCD)
  2. shell的if-else的基本用法
  3. redis10--主从模式
  4. [Java面经] 关于面试的二三事.
  5. Java MVC框架性能比较
  6. DataTable相关
  7. [案例分析] 打造值得信任的个人品牌究竟靠什么?
  8. JavaScript语言基础(一)
  9. Java远程连接进程
  10. html5 字符串对象,JavaScript核心对象-String对象