解析java中volatilekeyword
在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的更多相关文章
- 转:二十一、详细解析Java中抽象类和接口的区别
转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...
- XML解析——Java中XML的四种解析方式
XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四 ...
- 【java】解析java中的数组
目录结构: contents structure [+] 一维数组 1,什么是一维数组 2,声明一维数组的三种方式 二维数组 1,什么是二维数组 2,声明二维数组的3种方式 3,二维数组的遍历示例 数 ...
- xml解析----java中4中xml解析方法(转载)
转载:https://www.cnblogs.com/longqingyang/p/5577937.html 描述 XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与 ...
- XML解析——Java中XML的四种解析方式(转载 by 龍清扬)
XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四 ...
- 解析Java中的String、StringBuilder、StringBuffer类(一)
引言 String 类及其相关的StringBuilder.StringBuffer 类在 Java 中的使用相当的多,在各个公司的面试中也是必不可少的.因此,在本周,我打算花费一些时间来认真的研读一 ...
- 深入解析Java中的装箱和拆箱
自己主动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最主要的东西,再来看一以下试笔试中常常遇到的与装箱.拆箱相关的问题. 下面是本 ...
- 深度解析Java中的那把锁
锁的本质 我们先来讨论锁的出现是为了解决什么问题,锁要保证的事情其实很好理解,同一件事(一个代码块)在同一时刻只能由一个人(线程)操作. 这里所说的锁为排他锁,暂不考虑读写锁的情况 我们在这里打个比方 ...
- 深度解析Java中的5个“黑魔法”
现在的编程语言越来越复杂,尽管有大量的文档和书籍,这些学习资料仍然只能描述编程语言的冰山一角.而这些编程语言中的很多功能,可能被永远隐藏在黑暗角落.本文将为你解释其中5个Java中隐藏的秘密,可以称其 ...
随机推荐
- SDK_列表控件的使用
列表控件的使用 列表控件是通用控件,响应WM_NOTIFY 消息 主要包含了 4 种风格,我们学的是 report 风格 如何设置列表的扩展风格 LVS_EX_GRIDLINES: 列表拥有表格线 L ...
- RocketMQ学习笔记(13)----RocketMQ的Consumer消息重试
1. 概念 Producer端重试: 生产者端的消息失败,也就是Producer往MQ上发消息没有发送成功,比如网络抖动导致生产者发送消息到MQ失败. 这种消息失败重试我们可以手动设置发送失败重试的次 ...
- Python isalpha() 方法检测字符串是否只由字母组成。
Python isalpha() 方法检测字符串是否只由字母组成.
- CSDN怎么转载别人的博客
在参考"如何快速转载CSDN中的博客"后,由于自己不懂html以及markdown相关知识,所以花了一些时间来弄明白怎么转载博客,以下为转载CSDN博客步骤和一些知识小笔记. 参考 ...
- UVA - 820 Internet Bandwidth(最大流模板题)
题目: 思路: 直接套最大流的模板就OK了,注意一下输出的格式. 代码: #include <bits/stdc++.h> #define inf 0x3f3f3f3f #define M ...
- ubuntu tomcat自启动
1 编写启动文件/etc/init.d/tomcat7 文件内容如下:
- 【转】Flex 布局
网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中 ...
- Django-REST-Framework JWT 实现SSO认证(上)
一.什么是Django-REST-Framework? Django-REST-framework 是基于Django框架的一个web RESTful风格开发的框架,它可以实现API接口的快速开发,但 ...
- 【Codeforces 464A】No to Palindromes!
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 因为原序列没有任何长度超过2的回文串. 所以,我们在改变的时候,只要时刻保证改变位置s[i]和s[i-1]以及s[i-2]都不相同就好. 因为 ...
- 对jetbrains全系列可用例:IDEA、WebStorm、phpstorm、clion等----https://blog.csdn.net/u014044812/article/details/78727496
https://blog.csdn.net/u014044812/article/details/78727496 pyCharm最新2018激活码