Difference Between Volatile and Synchronized Keywords in Java

2018年8月25日
TCP三次握手四次挥手
2018年8月23日
常用的八种排序算法Java代码实现
2018年9月5日

Difference Between Volatile and Synchronized Keywords in Java

Difference Between Volatile and Synchronized Keywords in Java

 

volatile是一个变量修饰符,而synchronized修饰一段代码块和方法。

我们来看下下面的代码:

 

int  i1 ;              

int  geti1(){ return  i1 ;}

volatile  int  i2 ;              

int  geti2(){ return  i2 ;}        

int  i3 ;

synchronized  int  geti3(){ return  i3 ;}

 

在这里,我们定义了三个整型变量:i1 ,i2,和i3 。而且,我们定义了三种相应的getter方法:geti1(),geti2(),和geti3()。

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

线程可以具有变量的本地副本,并且数据不必与其他线程中保存的数据相同。特别是,另一个线程可能已将i1 在其线程中更新,但当前线程中的值可能与该更新值不同。实际上,Java演示了“主”内存的概念,而这是保存变量当前“正确”值的内存。线程可以拥有自己的变量数据副本,并且线程副本可以与“主”内存不同。

geti2() 从“主”存储器有效地访问i2的值。一个volatile 变量是不允许有一个变量是目前在“主”内存的值不同的本地副本。实际上,volatile声明的变量必须使其数据在所有线程之间同步,这样无论何时在任何线程中访问或更新变量,所有其他线程都会立即看到相同的值。通常,volatile变量具有比“普通”变量更高的访问和更新开销。典型的,允许线程拥有自己的数据副本,这样可以提高效率。

volatile和synchronized之间有两点不同:

首先,synchronized 取并释放监视器上的锁定,这些锁定强制一次只能一个线程执行代码块。这是synchronized一个相当着名的方面。但 synchronized也要同步内存。实际上,synchronized 是将整个线程内存与“主”内存同步。因此,执行geti3()时做了以下操作:

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

因此,volatile只在线程内存和“主”内存之间同步一个变量的值,synchronized同步线程内存和“主”内存 之间所有变量的值,并锁定和释放监视器以控制多个线程之间的所有权。

从这些信息可以得出结论,synchronized 可能比volatile有更多的开销。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注