`

java volatile关键字

    博客分类:
  • java
阅读更多

volatile关键字有什么用?

举个例子:

private volatile int v;
public void func(){ 
     int a=5*v;
     int b=5*v;
     ....
}
     如果v是个普通的变量,编译器很可能会做这样的优化,   第一次计算出5*v的值后,先赋给a,然后直接又从寄存赋给b,   而不会重新计算5*v, 如果这个时候其他线程改变了v的值,而本线程又没有去“主”内存里面取新的v值,就会造成b值的不正确。如果定义成volatile,编译器则不会做任何优化,每次都会重新读取v的值。
 

volatile和synchronized的有什么不同?

private int i1;
private volatile int i2;              
private int i3;
public int geti1() {
     return i1;
} 

public int geti2(){
     return i2;
} 
              
public synchronized int geti3() {
     return i3;
} 
     Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。 
     而 geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经 volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。 
     既然volatile关键字已经实现了线程间数据同步,又要 synchronized干什么呢?它们之间有两点不同。
     首先,synchronized需要获得并释放对象锁。其次,synchronized在“ 主”内存区域同步整个线程的内存。因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。 
     执行geti3()方法做了如下几步:
 
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放) 
2. 线程内存的数据被消除,从“主”内存区域中读入
3. 代码块被执行 
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值) 
5. 线程释放监视this对象的对象锁 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics