Java中volatile和synchronized关键字的区别

本文介绍了Java中一些基本但很重要的概念。

volatile是一个域修饰器(field modifier),而synchronized修饰代码块和方法。

因此,我们可以使用这两个关键字来指定一个简单累加器的三种变体。

int i1;              
int geti1() { return i1; }

volatile int i2;              
int geti2() { return i2; }        

int i3;
synchronized int geti3() { return i3; } 

上面,我们定义了3个整数变量:i1i2i3。并且,我们定义了3个对应的getter方法:geti1()geti2()geti3()

geti1()在当前线程访问当前存储在i1中的值。

线程可能有变量的本地拷贝,并且数据不保证与其它线程中保存的数据相同。特别是,其它线程可能在它的线程中已经更新了i1,但是在当前线程中这个值可能不同于那个更新后的值。事实上,Java演示了“主内存”的想法,对于变量,它保存当前“正确的”值。线程可能有它们自己的变量数据拷贝,并且,线程的拷贝可能不同于“主内存”。

因此,它是可能的,在“主内存”中i1的值是1,在线程1中i1的值是2,并且如果线程1和线程2都更新了i1,则在线程3中i1的值是3。但是,更新后的值并未被传播到“主内存”或是其它线程。

另一方面,geti2()从“主内存”中有效地访问i2的值。一个volatile变量不允许有线程的本地拷贝,这会导致该变量与“主内存”中当前保存的值不同。实际上,声明为volatile的变量必须在所有线程之间同步其数据,这样无论何时你在任何线程中访问或更新该变量,其它所有线程都会立即看到相同的值。一般来说,volatile变量有更高的访问和更新开销相比于普通变量。通常,为了提高效率,线程允许有它们自己的数据拷贝。

volatilesynchronized主要有两点差异:

首先,synchronized通过在监视器上获取和释放锁,来强制一次只能有一个线程执行一个代码块。这是synchronized的一个众所周知的方面。但是synchronized也同步内存。实际上,synchronized将整个线程内存和“主内存”同步。因此,运行geti3()会执行以下操作:

  1. 线程获取对象this的监视器上的锁;
  2. 线程内存刷新其所有变量,即其所有变量均有效地从“主内存”读取;
  3. 代码块被运行。在这种情形下,这意味着设置i3的当前值为返回值,它可能刚刚从“主内存”中重置;
  4. 任何对变量的改变一般会被写入到“主内存”,但是对于geti3(),我们没有改变;
  5. 线程释放对象this的监视器上的锁。

因此,volatile仅同步线程内存和“主内存”之间一个变量的值,synchronized同步线程内存与“主内存”之间所有变量的值,并且通过加解监视器上的锁以控制在多个线程之间的所有权。

从这个信息可以得出结论:synchronized相比于volatile可能有更多的开销。

原文:Difference Between Volatile and Synchronized Keywords in Java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值