voliate(轻量级的同步机制)

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:52   1023   0

voliate特点:

JMM内存模型三大特性:可见性,原子性,有序性。

1.禁止指令重排序:

voliate实现禁止指令重排,避免多线程环境下程序出现乱序执行的现象。
多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。
(初始排序是123,最后排序可能为213,禁止重排后初始和最后排序一致)
(重排:答题会做的先做,不会的后做,做题顺序和出题顺序不一致)


2.内存可见性:

线程首先将变量从主内存拷贝到自己的工作内空间,然后对变量进行操作,操作完再将变量写回主内存;第一时间通知其他线程,第一时间通知的机制就是Java(JMM内存模型)的可见性。


3.不保证原子性:

不能保证数据的完整性,会出现写覆盖,数据丢失。
解决原子性问题
1.加synchronized
2.使用juc下面的AtomicInteger;Atomic的底层原理是CAS

 AtomicInteger atomicInteger = new AtomicInteger();
    public void addMyAtomic(){
       atomicInteger.getAndIncrement();
   }


单例的模式:双端检索机制;在需要单例的对象前加voliate(禁止指令重排)

CAS(CompareAndSwap)底层原理:

比较并交换(比较当前工作内存中的值和主内存中的值是否一样,一样将内存值修改为更新值;如果不一样,重新获得主内存的值继续和工作内存中的值比较,直到一致为止)。
(getAndIncrement的底层调的是unsafe.getAndAddInt(this,valueOffset,1);this 当前对象;valueOffset:该对象的内存地址;1:需要变动的变量
这个对象的底层是CAS思想)

var1 AtomicInteger对象本身。
var2该对象值得引用地址。
var4需要变动的数量。
var5是用过var1 var2找出的主内存中真实的值。
用该对象当前的值与var5比较:
如果相同,更新var5+var4并且返回true,
如果不同,继续取值然后再比较,直到更新完成。

假设线程A和线程B两个线程同时执行getAndAddInt操作(分别跑在不同CPU上) :
1.AtomicInteger里 面的value原始值为5,即主内存中AtomicInteger的value为5,根据JMM模型,线程A和线程B各自持有一份值为5的value的副本分别到各自的工作内存。
2.线程A通过getIntVolatile(var1, var2)拿到value值5,这时线程A被挂起。
3.线程B也通过getIntVolatile(var1, var2)方法获取到value值5, 此时刚好线程B没有被挂起并执行compareAndSwapInt方法比较内存值也为5,成功修改内存值为6,线程B打完收工,一切0K。
4.这时线程A恢复,执行compareAndSwaplnt方法比较, 发现自己手里的值数字5和主内存的值数字6不-致,说明该值已经被其它线程抢先一步修改过了,那A线程本次修改失败,只能重新读取重新来一遍了。
5/线程A重新获取value值, 因为变量value被volatile修饰, 所以其它线程对它的修改,线程A总是能够看到,线程A继续执行compareAndSwaplnt进行比较替换,直到成功。


CAS的底层就是:Unsafe类+CAS思想(自旋)
内存值 V
旧的预期值 A
要修改的更新值 B
当且当 (内存值)V == A(预期值), V = B(将内存值修改为B)。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP