• volatile跟Java的内存模型有关,非volatile变量时,平常情况,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回。
  • valatile指的每次都读取主内存的值,有更新则立即写回主内存。
  1. “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性。
    1. “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性。
      1. “volatile保证了线程之间的可见性”:因为线程看到volatile变量会去读取主内存最新的值,而不是自个一直在那跟内部的变量副本玩,所以保证了valatile变量在各个线程间的可见性
        1. “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最经典理解的更多相关文章

  1. Android中一个经典理解误区的剖析

    今天,在Q群中有网友(@广州-包晴天)发出了网上的一个相对经典的问题,问题具体见下图. 本来是无意写此文的,但群里多个网友热情不好推却,于是,撰此文予以分析. 从这个问题的陈述中,我们发现,提问者明显 ...

  2. JS经典理解例子

    1. var name = 'the window'; var obj = { name:"my obj", getNameFunc:function(){ return func ...

  3. spring IOC经典理解

    不多解释,直接上图片!

  4. ORACLE RMAN增量备份经典理解

    http://blog.itpub.net/26118480/viewspace-1793548/

  5. python积累

    python积累 一.逐渐积累 python逐渐积累 http://www.cnblogs.com/lx63blog/articles/6051526.html python积累_2 http://w ...

  6. Java 设计模式系列(七)桥接模式

    Java 设计模式系列(七)桥接模式 桥接模式(Bridge)是一种结构型设计模式.Bridge 模式基于类的最小设计原则,通过使用封装.聚合及继承等行为让不同的类承担不同的职责.它的主要特点是把抽象 ...

  7. javascript的理解及经典案例

    js的简介: JavaScript是一种能让你的网页更加生动活泼的程式语言,也是目前网页中设计中最容易学又最方便的语言. 你可以利用JavaScript轻易的做出亲切的欢迎讯息.漂亮的数字钟.有广告效 ...

  8. 针对JS经典题型对全局变量及局部变量的理解浅谈

    第一次写博,还蛮激动... 看到了三题经典题型,就我目前的认识对此题进行总结.如有错误,敬请指正 首先,我们先明确一下JS引擎的工作步骤: js引擎工作分为两步: 1.将这个js中的变量和函数声明保存 ...

  9. IIS 7 托管管道模式 经典模式(Classic) 集成模式(Integrated) 分析与理解

    IIS 7.0 支持两种管道模式:一种是IIS 7.0最新提供的集成管道模式,另一种是经典管道模式,经典管道模式是由先前版本的IIS提供的. 我们可以通过应用程序池设置管道模式,这项功能对IIS管理员 ...

随机推荐

  1. 怎么删除Windows服务

    1,首先找到服务名字. 2,在cmd中进到c:下面 3,sc delete 名字. 删除成功

  2. shell常见操作整理(更新)

    查看文件第20到30行的内容 法一:[root@oldboy ~]# seq 100 > ett.txt [root@oldboy ~]# head -30 ett.txt | tail -11 ...

  3. grep常见操作整理(更新)

    提取邮箱和URL [root@test88 ~]# cat url_email.txt root@gmail.com,http://blog.peter.com,peter@qq.com [root@ ...

  4. LVS负载均衡DR模式

    什么是集群? 一组相互独立的计算机,利用高速通信网络组成的一个计算机系统,对于客户机来说像是一个单一服务器,实际上是一组服务器.简而言之,一堆机器协同工作就是集群.集群的基本特点:高性能.高并发.高吞 ...

  5. mui初探笔记

    /* MUI 使用说明: * * 1.每个用到mui的页面都调用下mui.init. * 2.如果需要使用大H5+对象,就写到plusReady中,如plus对象. */ '''[MUI开发注意事项] ...

  6. overflow属性在IE6下面失去效果

    自然状态下 overflow的属性设置,本来是超过了一定的长度时会自动产生滚动条,但是在ie6下面失效了. 例如:原来的代码: .code{overflow-x:auto;margin:5px aut ...

  7. NOIP 2012 Day1

    tags: NOIP 模拟 倍增 高精 Python categories: 信息学竞赛 总结 Luogu P1079 Vigenère 密码 Solution 表示并不是很懂其他人发的题解. 我是这 ...

  8. Java读写锁(ReentrantReadWriteLock)学习

    什么是读写锁 平时,我们常见的synchronized和Reentrantlock基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,哪怕是读操作.而读写锁是维护了一对锁(一个读锁和一个写锁), ...

  9. addeventlistener监听scroll跟touch

    这三个事件只在手机上生效 touchstart,手指开始触屏 touchmove,手指移动 touchend,手指触屏结束   这个事件在手机上跟在pc端都生效 scroll事件     addeve ...

  10. 利用flex布局来column分布

    html代码 <div class='items'> <div class='item'></div> <div class='item'></d ...