解析java中volatile关键字
在Java多线程编程中经常volatile,有时候这个关键字和synchronized 或者lock经常有人混淆,具体解析如下:
在多线程的环境中会存在成员变量可见性问题: java的每个线程都存在一个线程栈的内存空间,该内存空间保存了该线程运行时的变量信息,当线程访问某一个变量值的时候首先会根据这个变量的地址找到对象的堆内存或者是栈堆存(原生数据类型)中的具体的内容,然后把这个内同赋值一个副本保存在本线程的线程栈中,紧接着对这个变量的一切操作在线程完成退出之前都和堆栈内存中的变量内容是没有关系的,操作的是自己线程栈中的副本。当操作完后会把操作完的结果写回到主内存中。假如有两个线程A和B,同事操作某一个变量x;A对x进行了加1操作,那么B获取的副本可能是x加1后的结果,也可能是x;为了保证获取内存中最新的数据变量
需要加上 volatile 关键字,这样在每次对x进行操作的时候都会去检查下线程栈中的变量的值是不是和住内存中变量的值一样。如果不一样会重新load
public class ThreadSee {
//t1线程会根据flag的值做对应的操作,主线程会更改t1的值
public static void main(String[] args) throws InterruptedException {
ThReadTest th= new ThReadTest();
Thread t1 = new Thread(th);
t1.start();
Thread.sleep(1000);
th.changeFlag();
Thread.sleep(2000);
System.out.println(th.getFlag());
}
}
class ThReadTest implements Runnable{
//线程访问变量时会把其load到对应的线程栈中,每次操作时都要获取内存中最新的数据
private volatile boolean stopflag;
@Override
public void run() {
int i=0;
while(!stopflag){
i++;
System.out.println("=="+Thread.currentThread().getName());
}
System.out.println("Thread finish:"+i);
}
public void changeFlag(){
this.stopflag=true;
System.out.println(Thread.currentThread().getName()+"***********");
}
public boolean getFlag(){
return stopflag;
}
}
上述代码如果去掉volatile,会一直死循环执行下去。
但是volatile不能保证线程安全的同步
eg:
public class ThreadSave implements Runnable{
static ThreadSave sync = new ThreadSave();
static volatile int j=0;
//Lock lock =new ReentrantLock();
public void inscane(){
// lock.lock();
for(int i=0;i<10000000;i++){
j++;
}
// lock.unlock();
}
@Override
public void run() {
inscane();
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(sync);
Thread t2 = new Thread(sync);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(j);
}
}
根据上述代码执行的结果不是预期20000000,
因为对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的
例如假如线程1,线程2 在进行线程栈与主内存read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值
在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6
线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6
导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。
综上所述:
volatile只会保证线程去做一个检查当前线程栈的变量值和主内存中数据值是否一样的这么一个动作,只此而已。而lock或者是synchronized 会保证某一时刻只有单个线程进入该方法,从而确保其线程安全性。
所以在如果多个线程去修改一个volatile变量那么没有实际的逻辑意义。如果一个线程去修改其他的线程依赖修改的变量值,此时是有作用的
解析java中volatile关键字的更多相关文章
- 深入解析Java中volatile关键字的作用
转(http://m.jb51.net/article/41185.htm)Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制 在java线 ...
- 【转】java中volatile关键字的含义
java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- 转:java中volatile关键字的含义
转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- Java中Volatile关键字详解 (转自郑州的文武)
java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...
- Java中Volatile关键字详解
一.基本概念 先补充一下概念:Java并发中的可见性与原子性 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值, ...
- java中volatile关键字的理解
一.基本概念 Java 内存模型中的可见性.原子性和有序性.可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有 ...
- Java中Volatile关键字详解(转载)
转载自:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是 ...
- Java中volatile关键字解析
一.内存模型的相关概念 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存 ...
- java中volatile关键字的含义
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
随机推荐
- 【SqlServer系列】开启Sqlserver远程访问
1 概述 已发布[SqlServer系列]文章如下: [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [SqlS ...
- jsp: c:foreach 输出序号
关键在于<c:forEach>的varStatus属性,具体代码如下: <table width="500" border="0" cells ...
- LoadRunner接口工作总结
因为工作中需要开发维护类似枢纽性质的平台,所以经常利用LR进行接口测试.接口自动化测试.接口压力测试.用多了LR,有点不愿意使用报文编辑器进行手工接口测试了. 接口脚本操作过程: 首先:打开LR,N ...
- webpack热更新问题和antd design字体图标库扩展
标题也不知道怎么写好,真是尴尬.不过话说回来,距离上一次写文快两个月了,最近有点忙,一直在开发新项目, 今天刚刚闲下来,项目准备提测.借这个功夫写点东西,把新项目上学到的一些好的干活分享一下,以便之后 ...
- 消息中间件Client模块划分
上图是之间讨论确定的系统架构(后续内容会按照这个架构来叙述),其中: 客户端包含Producer和Consumer两大块 客户端需要和NameServer交互来获取元数据 客户端需要和Broker交互 ...
- 【AngularJS】学习资料
1. http://www.cnblogs.com/lcllao/tag/AngularJs/ http://www.ituring.com.cn/article/13474 http://www.a ...
- Postgres by BigSQL and Hadoop_fdw
Postgres by BigSQL and hadoop_fdw 测试Postgresql和远程Hive的Join操作. 测试环境 Centos6.8 HDP2.4集群,其中Hive Server2 ...
- yii2 获取从前台传过来的post数据
第一次使用yii写接口的时候,直接用了$_POST获取post数据,发现会报400错误,根本无法获取到post数据,用$_GET却能获取get数据. 纠结了很久,然后查资料,发现原来yii中默认的开启 ...
- [补档]暑假集训D7总结
刷题 上午刷了一上午的网络流 (md建图快建吐了),然后就搞了一个网络流的索引= = (实在看不下去那篇大长文了啊喂),然后发现都是水题= =,我还瞎××乱刷 下午--听说我要刷平衡树? Blog 日 ...
- mybatis example使用 and和or联合查询(转)
这两天项目用到ibatis,碰到and or的联合查询,语句像这样的 select * from table where xxx = "xxx" and (xx1="xx ...