volitale最经典理解
- volatile跟Java的内存模型有关,非volatile变量时,平常情况,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回。
- valatile指的每次都读取主内存的值,有更新则立即写回主内存。
- “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性。
- “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性。
- “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性
- “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性。
链接:https://zhuanlan.zhihu.com/p/28324074
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我们都知道线程是在寄存器中运行的,而变量是保存在内存中的,当线程需要使用普通变量时会把变量copy一份到寄存器中,然后进行(多次)使用、修改等操作,完成之后再将更新后的变量写到内存中。但是在线程对变量副本进行修改等操作时,内存中变量的变化对于该线程是不可见的,这种行为是线程不安全的。笔者截取了一小段代码为例来说明这个问题:
public class CThread extends Thread {
private OutputStream ous;
static boolean flag=true;
public CThread(OutputStream ous) {
super();
this.ous = ous;
}
@Override
public void run(){
while(flag){
Scanner c=new Scanner(System.in);
try {
ous.write((c.nextLine()+"\r\n").getBytes());
ous.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
在主函数中启动线程后将flag的值修改为false,线程很有可能继续运行。这是因为主函数中对变量flag的操作对线程不可见。即线程已经拷贝了一份flag的信息(拷贝时flag为true),然后在寄存器里进行一系列操作,当内存更新后线程不知道,仍然以副本中flag的值(true)在运行。
而volatile修饰的变量具有可见性,即保证线程读取到的是最新更新的值。线程不拷贝内存变量而是直接读取内存中的变量,当内存中变量被其他线程修改后线程能立马知道。volatile是比同步更轻量级的操作,同步是锁定变量,只允许一个线程对其进行操作,是原子性动作。
当然被volatile修饰的变量也不是绝对的线程安全的。
public class Test extends Thread{
private volatile static int count=0;
public static void main(String[] args) {
Test t= new Test();
t.test();
System.out.println(count);
}
public void test(){
for(int i=0;i<1000;i++){
new Test().start();
}
}
@Override
public void run(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
我运行的结果是:999
为什么不是理论上的1000呢?
假设count在内存中最新更新的值是666,才是a线程和b线程都读取了这个变量的值然后分别进行加1的操作,a更新内存的值为667,b也更新内存的值为667,这就导致了线程不安全。
volitale最经典理解的更多相关文章
- Android中一个经典理解误区的剖析
今天,在Q群中有网友(@广州-包晴天)发出了网上的一个相对经典的问题,问题具体见下图. 本来是无意写此文的,但群里多个网友热情不好推却,于是,撰此文予以分析. 从这个问题的陈述中,我们发现,提问者明显 ...
- JS经典理解例子
1. var name = 'the window'; var obj = { name:"my obj", getNameFunc:function(){ return func ...
- spring IOC经典理解
不多解释,直接上图片!
- ORACLE RMAN增量备份经典理解
http://blog.itpub.net/26118480/viewspace-1793548/
- python积累
python积累 一.逐渐积累 python逐渐积累 http://www.cnblogs.com/lx63blog/articles/6051526.html python积累_2 http://w ...
- Java 设计模式系列(七)桥接模式
Java 设计模式系列(七)桥接模式 桥接模式(Bridge)是一种结构型设计模式.Bridge 模式基于类的最小设计原则,通过使用封装.聚合及继承等行为让不同的类承担不同的职责.它的主要特点是把抽象 ...
- javascript的理解及经典案例
js的简介: JavaScript是一种能让你的网页更加生动活泼的程式语言,也是目前网页中设计中最容易学又最方便的语言. 你可以利用JavaScript轻易的做出亲切的欢迎讯息.漂亮的数字钟.有广告效 ...
- 针对JS经典题型对全局变量及局部变量的理解浅谈
第一次写博,还蛮激动... 看到了三题经典题型,就我目前的认识对此题进行总结.如有错误,敬请指正 首先,我们先明确一下JS引擎的工作步骤: js引擎工作分为两步: 1.将这个js中的变量和函数声明保存 ...
- IIS 7 托管管道模式 经典模式(Classic) 集成模式(Integrated) 分析与理解
IIS 7.0 支持两种管道模式:一种是IIS 7.0最新提供的集成管道模式,另一种是经典管道模式,经典管道模式是由先前版本的IIS提供的. 我们可以通过应用程序池设置管道模式,这项功能对IIS管理员 ...
随机推荐
- caffe Python API 之 数据输入层(Data,ImageData,HDF5Data)
import sys sys.path.append('/projects/caffe-ssd/python') import caffe4 net = caffe.NetSpec() 一.Image ...
- java的集合类面试题
转自:https://yq.aliyun.com/articles/78788?spm=5176.8252056.759076.3.uFYrmt java.util包中包含了一系列重要的集合类,而对于 ...
- FineReport——JS二次开发(下拉框)
下拉框显示多列时,输入的内容检索的内容为显示值整行数据,而不是实际值. 下拉框选择之后,控件显示的是显示值而非实际值. 对于下拉框显示队列,可以有多种方法,但是经过测试大多数方法不适用,检索效率太低, ...
- 如何生成[0,maxval]范围内m个随机整数的无重复的有序序列
在这里我们将待生成的数据结构称为IntSet,接口定义如下: class IntSetImp { public: IntSetImp(int maxelements,int maxval); void ...
- hdu 1087(LIS变形)
Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- 升级PIP源
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple django
- es6中对象的一些操坐
变量的赋值 key值得构建 对象的严格检测 对象的合并 1.变量的赋值: let name='宋宇',age='17岁': let obj={name,age} //快速的将变量引入到对象中去. 2. ...
- magento批量上传产品
Step1:表格仔细检查无误后,将准备好的图片上传至 media/import中.如果使用专用的图片服务器,把图片上传到服务器上,当然表格中的图片地址要做相应的修改. Step2:然后,登陆Magen ...
- cuda8.0 百度云盘分享
因为深度学习的需要,装了ubuntu16系统,同时也装了cuda,在下载cuda的时候发现教育网下载的速度不忍直视,故换了更快的网下载,结果发现10兆宽带下载速度依然很慢,不过总算还是下载了,故把千辛 ...
- 洛谷P2278 [HNOI2003] 操作系统
题目传送门 分析:题目中提到了优先级,很显然这题要用优先队列+模拟.题目中很多细节需要注意,还是在代码中解释吧,这里我用的是手打的堆. Code: #include<bits/stdc++.h& ...