在java多线程编程中常常volatile,有时候这个keyword和synchronized 或者lock常常有人混淆。详细解析例如以下:

在多线程的环境中会存在成员变量可见性问题: java的每一个线程都存在一个线程栈的内存空间,该内存空间保存了该线程执行时的变量信息。当线程訪问某一个变量值的时候首先会依据这个变量的地址找到对象的堆内存或者是栈堆存(原生数据类型)中的详细的内容,然后把这个内同赋值一个副本保存在本线程的线程栈中,紧接着对这个变量的一切操作在线程完毕退出之前都和堆栈内存中的变量内容是没有关系的,操作的是自己线程栈中的副本。当操作完后会把操作完的结果写回到主内存中。假如有两个线程A和B,同事操作某一个变量x;A对x进行了加1操作,那么B获取的副本可能是x加1后的结果,也可能是x;为了保证获取内存中最新的数据变量
须要加上 volatile keyword,这样在每次对x进行操作的时候都会去检查下线程栈中的变量的值是不是和住内存中变量的值一样。假设不一样会又一次load

eg:

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

导致两个线程及时用volatilekeyword改动之后,还是会存在并发的情况。

综上所述:

volatile仅仅会保证线程去做一个检查当前线程栈的变量值和主内存中数据值是否一样的这么一个动作。仅仅此而已。而lock或者是synchronized 会保证某一时刻仅仅有单个线程进入该方法,从而确保其线程安全性。

所以在假设多个线程去改动一个volatile变量那么没有实际的逻辑意义。假设一个线程去改动其它的线程依赖改动的变量值,此时是有作用的



解析java中volatilekeyword的更多相关文章

  1. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

  2. XML解析——Java中XML的四种解析方式

    XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四 ...

  3. 【java】解析java中的数组

    目录结构: contents structure [+] 一维数组 1,什么是一维数组 2,声明一维数组的三种方式 二维数组 1,什么是二维数组 2,声明二维数组的3种方式 3,二维数组的遍历示例 数 ...

  4. xml解析----java中4中xml解析方法(转载)

    转载:https://www.cnblogs.com/longqingyang/p/5577937.html 描述 XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与 ...

  5. XML解析——Java中XML的四种解析方式(转载 by 龍清扬)

    XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四 ...

  6. 解析Java中的String、StringBuilder、StringBuffer类(一)

    引言 String 类及其相关的StringBuilder.StringBuffer 类在 Java 中的使用相当的多,在各个公司的面试中也是必不可少的.因此,在本周,我打算花费一些时间来认真的研读一 ...

  7. 深入解析Java中的装箱和拆箱

    自己主动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最主要的东西,再来看一以下试笔试中常常遇到的与装箱.拆箱相关的问题. 下面是本 ...

  8. 深度解析Java中的那把锁

    锁的本质 我们先来讨论锁的出现是为了解决什么问题,锁要保证的事情其实很好理解,同一件事(一个代码块)在同一时刻只能由一个人(线程)操作. 这里所说的锁为排他锁,暂不考虑读写锁的情况 我们在这里打个比方 ...

  9. 深度解析Java中的5个“黑魔法”

    现在的编程语言越来越复杂,尽管有大量的文档和书籍,这些学习资料仍然只能描述编程语言的冰山一角.而这些编程语言中的很多功能,可能被永远隐藏在黑暗角落.本文将为你解释其中5个Java中隐藏的秘密,可以称其 ...

随机推荐

  1. TF实战:(Mask R-CNN原理介绍与代码实现)-Chapter-8

    二值掩膜输出依据种类预测分支(Faster R-CNN部分)预测结果:当前RoI的物体种类为i第i个二值掩膜输出就是该RoI的损失Lmask 对于预测的二值掩膜输出,我们对每个像素点应用sigmoid ...

  2. POJ_1088_(dp)(记忆化搜索)

    滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 95792   Accepted: 36322 Description ...

  3. POJ_2195_Going Home

    题意:用'H','m','.'作出矩阵,'H'代表房子,'m'代表人,人一次只能水平或者垂直移动到相邻的点,问所有人一共走的步数的最小值. 分析:明显的求二分图最大权匹配.KM算法求得的是最大权匹配, ...

  4. cmd命令安装、卸载、启动和停止Windows Service

    1.运行--〉cmd:打开cmd命令框 2.在命令行里定位到InstallUtil.exe所在的位置 InstallUtil.exe 默认的安装位置是在C:/Windows/Microsoft.NET ...

  5. Extjs二级联动combo省城市

    Extjs二级联动 Extjs combox根据省查询城市 实现效果如上图所示, store层代码: Ext.define("ExtApp.store.TeacherProvince&quo ...

  6. Object类型转换为String类型

    1. Object.toString() 1 obj.toString() 注意:必须保证Object不是null值,否则将抛出NullPointerException异常. 2. (String)O ...

  7. Session共享实现方案调研

    1.背景 随 着互联网的日益壮大,网站的pv和uv成线性或者指数倍的增加.单服务器单数据库早已经不能满足实际需求.目前大多数大型网站的服务器都采用了分布式服务 集群的部署方式,所谓集群,就是让一组计算 ...

  8. linux内核开发程序风格

    变量命名法 这里是linux不是windows,所以匈牙利命名法是不允许使用的,在内核中,局部变量只要可以明确表达自己的意思,可以使用idx,i这种名字的id, 全局函数和变量需要有表达性的名字例如g ...

  9. JSP内置对象说明

    JSP内置对象说明 制作人:全心全意 request对象:request对象封装了由客户端生成的HTTP请求的所有细节,主要包括HTTP头信息.系统信息.请求方式和请求参数等.通过request对象提 ...

  10. react入门----事件监听

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...