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)

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python unittest接口自动化测试实战_pytest测试框架从入门到精通

    python unittest接口自动化测试实战_pytest测试框架从入门到精通一、unittest工作原理unittest最核心的四部分是:TestCase,TestSuite,TestRunner,TestFixtureTestCase:用户自定义的测试case的基类,调用run()方法,会依次调用setUp方法、执行用例的方法、tearDown方法。TestSuite:测试用例集合,可以通过addTest()方法手动增加TestCase,也可以通过Test…

    2022年10月14日
    4
  • stringbuffer stringbuilder区别_javastringbuffer

    stringbuffer stringbuilder区别_javastringbufferString、StringBuffer和StringBuilder的区别:文章目录StringStringBufferStringBuilderStringBuffer是如何实现线程安全的呢?Java9的改进String  String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。  这个是String类的解释,之前小咸儿看…

    2022年4月19日
    50
  • datagrip 2021.11.4 激活码(JetBrains全家桶)

    (datagrip 2021.11.4 激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html0E14HXZ4QL-eyJsaWN…

    2022年3月29日
    53
  • macOS U盘制作启动系统

    macOS U盘制作启动系统

    2021年7月8日
    70
  • idea 社区版 区别_idea社区版有哪些功能不能用

    idea 社区版 区别_idea社区版有哪些功能不能用大家好,我是智能客服时间君,上述问题将由我为大家进行解答。idea社区版和商业版的区别:1、名称不同,idea商业版指的是IntelliJIDEAUltimate;idea社区版指的是IntelliJIDEACommunity。2、功能不同,IDEA商业版是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,主要功能为:智能代码助手、代码自动提示、重构、J…

    2022年9月15日
    0
  • python中读写LMDB数据库[通俗易懂]

    python中读写LMDB数据库[通俗易懂]转自原文:https://blog.csdn.net/dcrmg/article/details/79144507LMDB的全称是LightningMemory-MappedDatabase(快如闪电的内存映射数据库),它的文件结构简单,包含一个数据文件和一个锁文件:LMDB文件可以同时由多个进程打开,具有极高的数据存取速度,访问简单,不需要运行单独的数据库管理进程,只要在访问数据的代码…

    2022年9月29日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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