volatile不保证原子性

我的理解是,在volatile单独的读和写,都是直接从主内存中读,写入主内存,但是,在volatile i++的时候,另外一个线程假设已经改变了i的值,并写入主内存,并告诉其他线程你们缓存的数据已经失效了,但是本线程已经完成i++,并且不需要再读取i的值,我现在要做的事情是写i。所以我不会再去读取i的最新值。volatile保证的是,在读的时候会从主存中读,在写的时候写入主存。
在生成汇编代码时会在volatile修饰的共享变量进行写操作的时候会多出Lock前缀的指令

  • Lock前缀的指令会引起处理器缓存写回内存;
  • 一个处理器的缓存回写到内存会导致其他处理器的缓存失效;
  • 当处理器发现本地缓存失效后,就会从内存中重读该变量数据,即可以获取当前最新值。
    内存屏障(memory barrier)是一个CPU指令。基本上,它是这样一条指令: a) 确保一些特定操作执行的顺序; b) 影响一些数据的可见性(可能是某些指令执行后的结果)。编译器和CPU可以在保证输出结果一样的情况下对指令重排序,使性能得到优化。插入一个内存屏障,相当于告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行。内存屏障另一个作用是强制更新一次不同CPU的缓存。例如,一个写屏障会把这个屏障前写入的数据刷新到缓存,这样任何试图读取该数据的线程将得到最新值,而不用考虑到底是被哪个cpu核心或者哪个CPU执行的。
    如果让volatile满足原子性:
    1.运算结果并不依赖于变量当前的值,,或者确保只有一个线程改变量的值;
    2.变量不需要与其他变量共同参与不变约束;

synchronized 是原子的,lock 和unlock指令是原子的,虽然jvm没有开放给程序员使用,但是更高层指令monitorenter和monitorexit指令开放给程序员使用,反映到java代码中就是synchronized关键字。synchronized具有有序性,要求线程访问共享变量时只能“串行“执行
volatile具有有序性,包含禁止指令重排序的语义,其具有有序性;
synchronized具有可见性,获得锁时会从主存中获取最新值,释放锁时会将共享变量同步到主存中。
总结:synchronized具有有序性、原子性、可见性,volatile具体有序性、可见性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值