volatile 和 synchronized 比较

x33g5p2x  于2022-04-10 转载在 其他  
字(0.8k)|赞(0)|评价(0)|浏览(303)

一 使用上的区别

  • volatile 关键字只能用于修饰实例变量或者类变量,不能用于修饰方法、方法参数、局部变量和常量等。
  • synchronized 关键字不能用于对变量的修饰,只能用于修饰方法或者语句块。
  • volatile 修饰的变量可以为 null,synchronized 关键字同步语句块 monitor 对象不能为 null。

二 对原子性的保证

  • volatile 无法保证原子性。
  • 由于 synchronized 是一种排他机制,因此被 synchronized 关键字修饰的同步代码块是无法被中途打断的,因此能够保证原子性。

三 对可见性的保证

  • 两者都可以保证共享资源在多线程间的可见性,但是实现机制完全不一样。
  • synchronized 借助 JVM 指令 monitor enter 和 monitor exit 对通过排他方式使得同步代码串行化,在 monitor exit 时所有共享资源都将会被刷新到主内存中。
  • volatile 使用机器指令的方式迫使其他线程工作内存中的数据失效,不得不到主内存中进行再次加载。

四 对有序性的保证

volatile 关键字禁止 JVM 编译器以及处理器对其进行重排序,所以它能够保证有序性。

synchronized 关键字所修饰的同步方法可以保证顺序性,但是这中顺序性是以程序串行化执行换来的,在 synchronized 关键字所修饰的代码块中代码指令也会发生指令重排序的情况,比如:

synchronized(this){
    int x = 10;
    int y = 20;
    x++;
    y = y+1;
}

x 和 y 谁先定义以及谁先进行运算,对程序来说没有任何影响,另外 x 和 y 之间也没有依赖关系,但是由于 synchronized 关键字同步的作用,在 synchronized 的作用域结束时 x 必定是 11,y 必定是21,也就是说达到了最终的输出结果和代码编写顺序一致性。

五 其他

  • volatile 不会使线程陷入阻塞。
  • synchronize 关键字会使线程进入阻塞状态。

《新程序员》:云原生和全面数字化实践

50位技术专家共同创作,文字、视频、音频交互阅读

相关文章