温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java正确使用volatile的方法

发布时间:2021-02-07 14:59:26 来源:亿速云 阅读:193 作者:小新 栏目:编程语言

这篇文章主要介绍了java正确使用volatile的方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

volatile关键字在java多线程中有着比较重要作用,volatile主要作用是可以保持变量在多线程中是实时可见的,是java中提供的最轻量的同步机制。

可见性

在Java的内存模型中所有的的变量(这里的变量是类全局变量,并不是局部变量,局部变量在方法内并没有线程安全的问题,因为变量随方法调用完成而销毁)都是存放在主内存中的,而每个线程有自己的工作内存,每次线程执行时,会从主内存获取变量的拷贝,对变量的操作都在线程的工作内存中进行,不同线程之间也不能共享工作内存,只能从主内存读取变量的拷贝。具体可以通过下图来表示:

java正确使用volatile的方法

然而对于volatile(使用synchronized/final修饰都具有可见性)来说打破了上述的规则,即当线程修改了变量的值,其他线程可以立即知道该变量的改变。然而对于普通变量来说,当一个线程修改了变量,需要先将变量写回主内存,其他线程从主内存读取变量后才对该线程可见。似乎从以上的描述可以推导出只要使用volatile修饰的变量就可以保证该变量在多线程环境下操作是安全的,因为它对于所有线程的工作内存都是可见的也就是说一致的。这么理解确实没错,但是在java中很多运算都不是原子的,所以在java的一些运算中使用volatile并不能保证线程安全问题。让我们来看一个例子:

public class test{
private static volatile t=0;
 private static int add(){
  return t++;
 }

 public static void testVolatile(){
  for (int i=0;i<20;i++){
   Thread thread=new Thread(()-> {
    for (int j=0;j<1000;j++) {
     add();
    }
   });
   thread.start();
  }
  while (Thread.activeCount()>1){
   Thread.yield();
  }
  System.out.println(t);
 }

 public static void main(String[] args){
  testVolatile();
 }
}

预期这个t值应该是20000,但是会出现t值小于20000的情况,原因大家应该猜到了,问题出在t++上,t++并不是一个原子操作,t++的操作在java中代表先获取t值,再加1,再赋值还t。在获取t值时因为是volatile修饰的,所以可以获取线程最新值,然而在加1的时候就不能保证了,有可能其他线程已经加1了。

那么什么场景使用volatile是最合适的呢?

* 在变量运算不依赖当前值

* 变量不需要与其他状态变量共同参与不变约束

翻译成中文就是对于那些在多线程中既有读又有写的变量,完全可以使用volatile修饰,这样就对于读操作就不要使用lock/synchronized比较重的操作了,直接读就是,因为变量是可见的。

感谢你能够认真阅读完这篇文章,希望小编分享的“java正确使用volatile的方法”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI