博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中synchronized与volatile的区别与联系
阅读量:4179 次
发布时间:2019-05-26

本文共 1683 字,大约阅读时间需要 5 分钟。

在Java多线程编程中,synchronized是非常常用的关键字,而volatile关键字比较罕见。

volatile关键字用以避免因缓存(caching)或重排(reordering)而导致当前线程读取过时的数据。任何时候,线程读取的都是主线程内存中的最新数据。

在Java 1.5之前,多线程对volatile变量的访问是无法被重排的,但是对非volatile变量的访问是被重排的。这使得多线程在同时访问volatile变量和非volatile变量时,volatile变量无法被用作多线程的信号条件。因为虽然保证了volatile变量是最新的,但是不能保证非volatile变量是最新的。

从Java 1.5开始,volatile关键字被赋予了新的特性,更加接近synchronized的严格。对volatile变量的读操作就类似于对内存访问的加锁,对volatile变量的写就类似于对内存访问的释放锁。

由于对volatile变量和非volatile变量之间的重排设置了更加严格的限制,虽然volatile变量仍然无法被重排,但是对非volatile变量的重排也不那么容易了,从而使得volatile变量有可能作为信号条件。示例如下:

class VolatileExample {  int x = 0;  volatile boolean v = false;  public void writer() {    x = 42;    v = true;  }  public void reader() {    if (v == true) {      //uses x - guaranteed to see 42.    }  }}
说明:由于在writer()方法中修改volatile变量v的同时,也修改了非volatile变量x,所以在Java 1.5中,对于执行reader()方法的线程来说,volatile变量v和非volatile变量x的最新值都是可见。而在Java 1.5之前,是无法保证非volatile变量x是最新值的。

当然,这也是有条件的,那就是多线程之间设置了准确的happens-before关系,即写入线程与读取线程操作的是同一个volatile变量v,即加的锁(类似锁但实际不是锁)与释放的锁匹配。

synchronized与volatile的主要区别有2点:

首先,从用法上,synchronized往往作用于方法或代码块,而volatile往往修饰变量。

其次,从实现机制上,synchronized是利用锁实现互斥访问。而volatile没有利用锁,而是利用内存共享,即volatile变量只在主线程中有一份,所有其他线程都共享这一份,因而一个线程对内存执行了写操作,所有其他线程立刻就能够读到最新的数据。

synchronized与volatile的对比:

Characteristic Synchronized Volatile
Type of variable Object Object or primitive
Null allowed? No Yes
Can block? Yes No
All  on access? Yes From Java 5 onwards
When synchronization happens When you explicitly enter/exit asynchronized block Whenever a volatile variable is accessed.
Can be used to combined several operations into an atomic operation? Yes Pre-Java 5, no.  possible in Java 5.

参考文献:

https://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#volatile

转载地址:http://dnlai.baihongyu.com/

你可能感兴趣的文章
HTML5学习之——HTML 5 应用程序缓存
查看>>
HTML5学习之——HTML5 内联 SVG
查看>>
HTML5学习之——HTML 5 服务器发送事件
查看>>
SVG学习之——HTML 页面中的 SVG
查看>>
SVG 形状学习之——SVG圆形
查看>>
SVG 滤镜学习之——SVG 滤镜
查看>>
mysql中用命令行复制表结构的方法
查看>>
hbase shell出现ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException
查看>>
让代码变得更优雅-Lombok
查看>>
解决Rhythmbox乱码
查看>>
豆瓣爱问共享资料插件发布啦
查看>>
Ubuntu10.10 CAJView安装 读取nh\kdh\caj文件 成功
查看>>
kermit的安装和配置
查看>>
vim 配置
查看>>
openocd zylin
查看>>
进程创建时文件系统处理
查看>>
内核线程创建
查看>>
linux中cat命令使用详解
查看>>
java中的异常机制
查看>>
商务智能-基本方法-数据钻取
查看>>