java voliate_voliate关键字及其示例

java voliate_voliate关键字及其示例voliate关键字1使变量在线程间可见对于避免不可见性问题,Java还提供了一种弱形式的同步,即使用了volatile关键字。该关键字确保了对一个变量的更新对其他线程可见。当一个变量被声明为volatile时候,线程写入时候不会把值缓存在寄存器或者或者在其他地方,当线程读取的时候会从主内存重新获取最新值,而不是使用当前线程的拷贝内存变量值。volatile虽然提供了可见性保证,但是不能使用他来…

大家好,又见面了,我是你们的朋友全栈君。

voliate关键字

1 使变量在线程间可见

对于避免不可见性问题,Java还提供了一种弱形式的同步,即使用了volatile关键字。该关键字确保了对一个变量的更新对其他线程可见。当一个变量被声明为volatile时候,线程写入时候不会把值缓存在寄存器或者或者在其他地方,当线程读取的时候会从主内存重新获取最新值,而不是使用当前线程的拷贝内存变量值。volatile虽然提供了可见性保证,但是不能使用他来构建复合的原子性操作,也就是说当一个变量依赖其他变量或者更新变量值时候新值依赖当前老值时候不在适用。与synchronized相似之处在于如图

fe24f3747062

如图线程A修改了volatile变量b的值,然后线程B读取了改变量值,那么所有A线程在写入变量b值前可见的变量值,在B读取volatile变量b后对线程B都是可见的,图中线程B对A操作的变量a,b的值都可见的。volatile的内存语义和synchronized有类似之处,具体说是说当线程写入了volatile变量值就等价于线程退出synchronized同步块(会把写入到本地内存的变量值同步到主内存),读取volatile变量值就相当于进入同步块(会先清空本地内存变量值,从主内存获取最新值)。

/**

* Created by lixiaodong on 2017/6/23.

*/

public class Test extends Thread{

//voliate

private String i =”sss”;

private void setI(String i){

this.i=i;

}

@Override

public void run() {

System.out.println(“进入方法”+i);

while (i.equals(“sss”)){

// System.out.println(“方法执行”);

//

// try {

// Thread.sleep(3000);

// } catch (InterruptedException e) {

// e.printStackTrace();

// }

}

System.out.println(“线程结束”);

}

public static void main(String[] args ) throws InterruptedException{

Test test=new Test();

test.start();

Thread.sleep(1000);

System.out.println(“线程设置了stop”);

test.setI(“线程设置了stop”);

}

}

上面是一个简单的示例。

首先运行代码,可以看到,尽管将变量设置了stop,test线程并没有如预期的停止.说明,test线程内的i的并没有被修改,test只是在start时将i变量拷贝到了线程自有的一块空间内,与主线内的i变量互不影响.

将voliate关键字放在变量i的声明上,运行发现程序正常停止.可见变量i在任何一个线程内都是可见的,当变量i在主线程被修改时,子线程立即获得了被更新的值.

最坑的地方来了,打开代码中的while循环中的打印语句,将voliate关键字注释掉,执行代码.神奇的事情发生了,程序正常的停止了,WTF!(在我最开始研究voliate的时候,我一直有这句输出语句,一直得不到正确结果)这是为啥呢?下面这段话基本说明了问题,同时你也可以将输出语句注释点,打开sleep的注释,看看结果.

JVM会尽力保证内存的可见性,即便这个变量没有加同步关键字。换句话说,只要CPU有时间,JVM会尽力去保证变量值的更新。这种与volatile关键字的不同在于,volatile关键字会强制的保证线程的可见性。而不加这个关键字,JVM也会尽力去保证可见性,但是如果CPU一直有其他的事情在处理,它也没办法。最开始的代码,一直处于试了循环中,CPU处于一直被饱受占用的时候,这个时候CPU没有时间,JVM也不能强制要求CPU分点时间去取最新的变量值。而加了System.out.println之后,由于内部代码的同步关键字的存在,导致CPU的输出其实是比较耗时的。这个时候CPU就有可能有时间去保证内存的可见性,于是while循环可以被终止。其实,也可以在while循环里面加上sleep,让run方法放弃cpu,但是不放弃锁,这个时候由于CPU有空闲的时候就去按照JVM的要求去保证内存的可见性。如下图所示。 run方法里面休息了3秒,cpu有充足的空闲时间去取变量的最新值,所以循环执行一次就停止了。(转自http://blog.csdn.net/weililansehudiefei/article/details/70904111)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/131410.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • containsKey使用方法[通俗易懂]

    containsKey使用方法[通俗易懂]作用是判断Map中是否有所需要的键值,下面是具体的代码:

  • verilog_移位寄存器_仿真(程序逐句解释)

    verilog_移位寄存器_仿真(程序逐句解释)前言  之前老是想着学的快点,就直接编译了程序就下载在开发板上跑,后来发现这样不行,因为如果程序有问题,验证和纠错的时间成本太高了(毕竟vivado跑一次花的时间很长),反过来学习仿真,下面是一点心得和体会。开发环境编译软件及版本:vivado2019.2编译语言:verilog  网上随便找了一个简单程序和仿真,先实现复现,再谈其他。下面我将先给出代码和仿真截图,再说具体的东西。移位寄存器程序代码:`timescale1ns/1ps/////////////////////////

  • windows cmd定时关机命令

    windows cmd定时关机命令windowscmd定时关机命令#7200为倒计时关机时间,单位秒shutdown-S-T7200

  • viewpager嵌套viewpager

    viewpager嵌套viewpagerviewpager嵌套viewpager要求:外层不可以滑动,内层可以滑动实现:重写外层的viewpager的2个方法即可publicclassNoScrollViewPagerextendsViewPager{publicNoScrollViewPager(Contextcontext){super(context);}public

  • 微机原理课程设计电梯控制系统_列举一个计算机控制系统的应用实例

    微机原理课程设计电梯控制系统_列举一个计算机控制系统的应用实例1、针对一个具有大纯时延时间的一阶惯性环节(G(s)=K*e-θs/(Ts+1))温度控制系统和给定的系统性能指标,(工程要求相角裕度为30~60,幅值裕度>6dB);要求测量范围-50℃~200℃,测量精度0.5%,分辨率0.2℃;2、书面设计一个计算机控制系统的硬件布线连接图,并转化为系统结构图;3、选择一种控制算法并借助软件工程知识编写程序流程图;4、用MATLAB和SIMULINK进…

  • 死链检查工具

    死链检查工具一:CheckMyLinksCheckMyLinks是一种浏览器工具,可以直接安装在谷歌浏览器上,安装完毕,打开相应网站,只要点击开启按钮,CheckMyLinks就会自动检测网页上的所

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号