volatile和synchronized的区别

本文探讨了Java并发编程中的volatile关键字与synchronized关键字的区别。深入解析了它们如何解决多线程环境下的可见性与原子性问题,并通过对比强调了各自的特点及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

volatile和synchronized的区别

在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型

详情请看:https://baike.baidu.com/item/java内存模型/3399303

导致多线程开发比较困难的点有两点:

  1. 线程之间如何通信:
  • 共享内存:通过读写内存的公共状态进行隐式传递
  • 消息传递:通过wait()/notify()/notifyAll()等方式,通过发送消息进行显示传递
  1. 线程之间如何同步:
  • 在共享内存的并发模型中,同步是显示做的;synchronized
  • 在消息传递的并发模型中,由于消息的发送必须在消息接收之前,所以同步是隐式的。

说明:Java里面所有的实例域、静态域、数组元素都存储在堆内存中的,堆内存是在多线程之间共享的;局部变量、方法、定义参数或者异常处理不会在线程之间共享的。是否共享导致了内存可见性的问题。(多线程读写同一个文件,多读多写同步进行,会导致混乱) 从上图看线程A和线程B什么时候去同步和更新主内存的共享内存都是不确定的,不确定的因素导致线程安全和线程可见性问题。

 这时候引入volatile。
  • 对于申明了volatile的变量在写操作的时候,JVM向处理器发送一条lock前缀的指令,把这个变量所在缓存行的数据写回到系统内存(主内存);
  • 在多处理器的情况下,保证各个处理器缓存一致性的特点,就会实现缓存一致性协议。这里类似分布式情况下的多个数据库数据一致性、原子性。
  • 每个处理器都去主内存中去检测自己本地缓存中的数据是否过期了(地址修改了),若修改了标志数据失效,当处理器对数据修改的时候,会去主内存同步数据到本地内存。 volatile可以做到原子性、可见性。不能保证复合操作的原子性。优点:相对synchronized开销小。

而synchronized:可重入性、互斥性、可见性。基于JVM实现的 以上是简单的实例在javap指令下查看其java编译器生成的字节码(JVM层面操作,所以synchronized没有源码)。 monitorenter和monitorexit分别是进入监视器,退出监视器,类似加锁和解锁。需要进入锁才能执行后面的方法。

转载于:https://my.oschina.net/MjShao/blog/1834886

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值