volatile 和 synchronzied 的区别
作者简介:悟空,8 年一线互联网开发和架构经验,用故事讲解分布式、架构设计、Java 核心技术。《JVM 性能优化实战》专栏作者,开源了《Spring Cloud 实战 PassJava》项目,公众号:悟空聊架构。本文已收录至 www.passjava.cn
volatile 和 synchronzied 的区别
volatile 只能修饰实例变量和类变量,synchronized 可以修饰方法和代码块。
volatile 不保证原子性,而 synchronized 保证原子性
volatile 不会造成阻塞,而 synchronized 可能会造成阻塞
volatile 轻量级锁,synchronized 重量级锁
volatile 和 synchronized 都保证了可见性和有序性
volatile 小结
volatile 保证了可见性:当一个线程修改了共享变量的值时,其他线程能够立即得知这个修改。
volatile 保证了单线程下指令不重排:通过插入内存屏障保证指令执行顺序。
volatitle 不保证原子性,如 a++这种自增操作是有并发风险的,比如扣减库存、发放优惠券的场景。
volatile 类型的 64 位的 long 型和 double 型变量,对该变量的读/写具有原子性。
volatile 可以用在双重检锁的单例模式种,比 synchronized 性能更好。
volatile 可以用在检查某个状态标记以判断是否退出循环。
补充案例
volatile 为什么不保证原子性,在单线程的场景,答案是 20000,如果是多线程的场景下呢?答案是可能是 20000,但很多情况下都是小于 20000。
怎么保证输出结果是 20000 呢?
synchronized 同步代码块
我们可以通过使用 synchronized 同步代码块来保证原子性。从而使结果等于 20000

但是使用 synchronized 太重了,会造成阻塞,只有一个线程能进入到这个方法。我们可以使用 Java 并发包(JUC)中的 AtomicInterger 工具包。
AtomicInterger 原子性操作
我们来看看 AtomicInterger 原子自增的方法 getAndIncrement()

多次运行的结果都是 20000。

版权声明: 本文为 InfoQ 作者【悟空聊架构】的原创文章。
原文链接:【http://xie.infoq.cn/article/bc7bcd669cf7b23fa6df71a4c】。文章转载请联系作者。
评论