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管理员 ...
随机推荐
- C基础 一个可以改变linux的函数getch
引言 - getch简述 引用老的TC版本getch说明. (文章介绍点有点窄, 应用点都是一些恐龙游戏时代的开发细节) #include <conio.h> /* * 立即从客户端 ...
- 对list对象进行排序
List<LjlSevOrdersVO> list = ljlSevOrdersService.findSevForOrders(ljlSevOrdersVO); //查出所有是自愿者的订 ...
- Mui自定义时间格式:
Mui自定义时间格式: (function($) { $.init(); $(document).on('tap','.btn',function(){ var obj = getFormJson($ ...
- DRF的@action装饰器
# 转自:http://www.cnblogs.com/zhzhlong/p/9325180.html 视图集中附加action的声明 from rest_framework.decorators i ...
- [转] Socket心跳包异常检测的C语言实现,服务器与客户端代码案例
转载自:zxh2075的专栏 在Socket心跳机制中,心跳包可以由服务器发送给客户端,也可以由客户端发送给服务器,不过比较起来,前者开销可能较大.本文实现的是由客户端给服务器发送心跳包,服务器不必返 ...
- win10网速慢
升级到win10之后发现网速特别慢,搜了下,网上的解决办法果然好使,按照如下操作即可. 返回桌面,按WIN+R键组合,运行gpedit.msc 打开组策略 依次展开管理模板->网络->Qo ...
- Java之IO流的关闭
1.在finally中关闭流: OutputStream out = null; try { out = new FileOutputStream(""); // ...操作流代码 ...
- cocos2dx 大地图分块加载的研究(初)
http://blog.csdn.net/dinko321/article/details/46739563 http://blog.csdn.net/u012812482/article/detai ...
- oracle 优化方案小记
1. 目前状况 1.1 表空间未合理规划,导致所有的用户下的所有表都创建在默认的表空间下 oracle 使用过程中未针对特定数据表进行特定的表空间规划,导致目前实例中所有的数据库表都存储中默认的表空间 ...
- 转:nginx+CGI/FASTCGI
简介版: 1.fastcgi与cgi区别:fastcgi通过线程来响应请求,而cgi对每个请求生成一个进程. 2.典型nginx数据传输过程:user->nginx->本地socket(请 ...