解析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中隐藏的秘密,可以称其 ...
随机推荐
- 【PostgreSQL-9.6.3】LOG: unrecognized configuration parameter "dynamic_shared_memory_type"
报错如下: 输入如下命令启动PG数据库时,报错: [postgres@drz ~]$ pg_ctl -D /opt/postgresql/data/ start server starting FAT ...
- 云服务IaaS,PaaS,SaaS
IaaS:基础设施服务,Infrastructure-as-a-service PaaS:平台服务,Platform-as-a-service SaaS:软件服务,Software-as-a-serv ...
- UML实例教程 解析UML建模分析与设计
UML统一建模语言在软件开发过程中非常实用,UMl建模的分析与设计你是否熟悉,这里就通过实例向大家介绍,希望通过本文的学习,你对UML建模的分析与设计方法有一定的了解. 本节向大家介绍一下图书管理系统 ...
- docker常用命令理解
docker help Commands: attach Attach local standard input, output, and error streams to a running con ...
- 00HyperText Markup Language
HyperText Markup Language HTML超文本标记语言是一种用于创建网页的标准标记语言用于显示网页内容,HTML运行在浏览器上,由浏览器来解析,您可以使用 HTML 来建立自己的 ...
- Python基础之字符的编码
参考原文 Python廖雪峰 为什么要进行编码? 计算机只能处理二进制数字(0100111),要处理文本,就必须先把文本转为数字才能处理,这个过程就叫编码. 字符的编码 ASCII编码 由于计算机是美 ...
- SIGFPE能处理上下溢吗?
SIGFPE可以报告算术异常.包括上下溢.除零等. C标准库说: 各种实现报告的异常类型区别也很大,但几乎没有实现会报告整型溢出. 真的吗?我测试了一下,发现在GCC上,整型.浮点上下溢都不会报告,但 ...
- ajax aspx调用webservice,返回json
1,创建一个asp.net网站 2.创建一个student类 using System; using System.Collections.Generic; using System.Linq; us ...
- CSS 嵌入,及其选择器
CSS 1. CSS样式表的几种使用方式 1.元素内嵌 <p style="font-size"></p> 2.内部文档内嵌 <style type= ...
- Python使用Flask框架,结合Highchart,搭配数据功能模块处理csv数据
参考链接:https://www.highcharts.com.cn/docs/data-modules 1.javascript代码 var csv = document.getElementByI ...