并发编程 atomic collections

来源:互联网 发布:淘宝网短袖圆领男内衣 编辑:程序博客网 时间:2024/05/23 15:03

CAS算法:

CAS 的全称是 Compare And Swap 即比较交换,其算法核心思想如下
函数:CAS(V,E,N) 参数:V 表示要更新的变量 E 预期值 N 新值

如果 V 值等于 E 值,则将 V 的值设为 N。若 V 值和 E 值不同,则说明已经有其他线程做了 更新,则当前线程什么都不做。通俗的理解就是 CAS 操作需要我们提供一个期望值,当期 望值与当前线程的变量值相同时,说明还没线程修改该值,当前线程可以进行修改,也就是 执行 CAS 操作,但如果期望值与当前线程不符,则说明该值已被其他线程修改,此时不执 行更新操作,但可以选择重新读取该变量再尝试再次修改该变量,也可以放弃操作

Java 的 CAS 操作通过 Unsafe 类来完成里面基本都是 native,即通过 JNI 调用 c/c++等代码

基本类型:
AtomicBoolean:原子更新布尔类型。
AtomicInteger:原子更新整型。
AtomicLong:原子更新长整型。
数组类:
AtomicIntegerArray:原子更新整型数组里的元素。
AtomicLongArray:原子更新长整型数组里的元素。
AtomicReferenceArray:原子更新引用类型数组里的元素。
引用类型:
AtomicReference:原子更新引用类型。
AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子的更新一个布尔 类型的标记位和引用类型。构造方法是 AtomicMarkableReference(V initialRef, boolean initialMark)

CAS 优缺点
优点:非阻塞算法
缺点:ABA 问题、循环开销大、只保证一个共享变量原子操作

ABA问题:

ABA:如果另一个线程修改V值假设原来是A,先修改成B,再修改回成A。当前线程的CAS操作无法分辨当前V值是否发生过变化。关于ABA问题我想了一个例子:在你非常渴的情况下你发现一个盛满水的杯子,你一饮而尽。之后再给杯子里重新倒满水。然后你离开,当杯子的真正主人回来时看到杯子还是盛满水,他当然不知道是否被人喝完重新倒满。解决这个问题的方案的一个策略是每一次倒水假设有一个自动记录仪记录下,这样主人回来就可以分辨在她离开后是否发生过重新倒满的情况。这也是解决ABA问题目前采用的策略。

参考资料:https://www.zhihu.com/question/23281499/answer/24112589

阅读全文
0 0