Java中volatile和synchronized的区别及其同步原理

volatile和synchronized的区别

区别

总结以下几条:
  1、从功能上,volatile是告诉jvm当前变量在寄存器中的值是不对的,需要从主存中读取;synchronized是锁定当前变量或者代码,只有当前线程可以访问,其他线程被阻塞。
  2、volatile只能修饰变量。synchronized可以修饰类、方法、静态方法、方法块。其中其修饰类、静态方法时作用的这个类的所有对象。如果子类重写父类的synchronized的方法且不加synchronized修饰,子类不会继承父类的synchronized关键字,即子类的方法默认不同步。
  3、volatile是轻量级的;synchronized是重量级的。
  4、volatile只保证有序性和可见性;synchronized保证原子性、有序性和可见性。
  5、volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

实现原理

volatile如何实现可见性和有序性?
  1、可见性
  对volatile修饰的变量进行赋值修改的时候,JIT编辑器所生成汇编代码会在最后有一行:

0x01a3de24:lock addl $0x0,(%esp);

代码是什么不重要,这行代码的作用是对原值加0,是一个空操作,lock前缀指令的作用是:将当前处理器缓存行的数据写回系统内存;这个写操作会使在其他CPU或者别的内核缓存了该内存地址的数据无效。而缓存一致性协议,当其他线程操作该变量时发现其无效了,就会去系统内存去重新读取数据,这就保证了被volatile修饰的变量对所有线程可见。
  2、有序性
  这是因为volatile变量在执行赋值操作后会产生一个内存屏障,在执行到内存屏障时,其前面的所有操作都已经完成,其后面的操作不会早于内存屏障执行。
  举个例子:

// 线程A:
a = 1;  // volatile a = 1;
b = 2;
// 线程B
while(true){
	if(b == 2){
		c = a;
	...
	}
}

变量a未被volatile修饰时,由于重排序,线程A可能先执行b=2,此时线程B运行,满足进入判断条件,对c进行了赋值,但却不是想要的1,而如果a被volatile修饰,则不会出现这个问题。

synchronized实现原理
  sychronized实现互斥同步的原理。sychronized关键字进行编译后,会在同步块的前后形成monitorenter和monitorexit两个字节码命令。在执行monitorenter命令时,首先尝试获取sychronized指定对象的锁,如果该对象未被锁定,则当前线程获取该对象的锁,并将锁的计数器加1,相应的,执行monitorexit命令时,锁的计数器减1,减到0的时候,释放该对象的锁。如果获取该对象的锁失败,则会进入阻塞状态,直到对象锁被另一个线程释放。当然,对于同一线程,synchronized同步块时可重入的,不会出现自己把自己锁死的情况,重入时,锁计数器加1。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值