volatile 关键字的两层语义

一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序

方式一:变量不使用 volatile 修饰

public class VolatileTest extends Thread {
private static boolean flag = false; public void run() {
while (!flag) ;
} public static void main(String[] args) throws Exception {
new VolatileTest().start();
Thread.sleep(2000);
flag = true;
}
}

方式二:变量使用 volatile 修饰

public class VolatileTest extends Thread {
private static volatile boolean flag = false; public void run() {
while (!flag) ;
} public static void main(String[] args) throws Exception {
new VolatileTest().start();
Thread.sleep(2000);
flag = true;
}
}

运行结果

方式一:线程不会结束

方式二:线程会结束

public class TestMain {
public static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
}
System.out.println(Thread.currentThread().getName() + "线程停止,死循环被打开");
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = false;
System.out.println(Thread.currentThread().getName() + "修改 flag 为" + flag);
}
}).start(); Thread.sleep(Integer.MAX_VALUE);
}
}

public class RunThread extends Thread {
/** volatile */
private volatile boolean isRunning = true; private void setRunning(boolean isRunning) {
this.isRunning = isRunning;
} public void run() {
System.out.println("进入 run() 方法中...");
while (isRunning == true) {
// doSomething()
}
System.out.println("线程结束了...");
} public static void main(String[] args) throws InterruptedException {
RunThread myThread = new RunThread();
myThread.start();
Thread.sleep(3000);
myThread.setRunning(false);
System.out.println("isRunning 的值已经设置为了 false");
Thread.sleep(1000);
System.out.println(myThread.isRunning);
}
}

public class RunThread extends Thread {
/** volatile */
private boolean isRunning = true; private void setRunning(boolean isRunning) {
this.isRunning = isRunning;
} public void run() {
System.out.println("进入 run() 方法中...");
while (isRunning == true) {
// doSomething()
}
System.out.println("线程结束了...");
} public static void main(String[] args) throws InterruptedException {
RunThread myThread = new RunThread();
myThread.start();
Thread.sleep(3000);
myThread.setRunning(false);
System.out.println("isRunning 的值已经设置为了 false");
Thread.sleep(1000);
System.out.println(myThread.isRunning);
}
}

volatile 的一个经典例子的更多相关文章

  1. 转:一个经典例子让你彻彻底底理解java回调机制

    一个经典例子让你彻彻底底理解java回调机制 转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17483273 ...

  2. 一个经典例子让你彻彻底底理解java回调机制

    转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17483273),请尊重他人的辛勤劳动成果,谢谢 所谓回调: ...

  3. 回调--一个经典例子让你彻彻底底理解java回调机制

    本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17483273),请尊重他人的辛勤劳动成果,谢谢 以前不理解什么叫回调 ...

  4. Java内存模型一个经典例子-指令重排序与CPU指令多发射导致执行结果异常

    先上代码: import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; ...

  5. MVVM模式的一个小例子

    使用SilverLight.WPF也有很长时间了,但是知道Binding.Command的基本用法,对于原理性的东西,一直没有深究.如果让我自己建一个MVVM模式的项目,感觉还是无从下手,最近写了一个 ...

  6. python之路第五篇之递归(进阶篇:续:经典例子剖析)

    递归 在函数内部,可以调用其他函数; 如果一个函数在内部调用自身本身,这个函数就是递归函数. 例如,我们来计算阶乘: n! = 1 x 2 x 3 x ... x n, 用函数f1(n)表示,可以看出 ...

  7. linux Posix 信号量 三 (经典例子)

    本文将阐述一下信号量的作用及经典例子,当中包括“<越狱>寄信”,“家庭吃水果”,“五子棋”,“接力赛跑”,“读者写者”,“四方恋爱”等 首先,讲 semWait操作(P操作)和semSig ...

  8. sql优化经典例子

    场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表 create table Course( c_id int PRIMARY KEY, name varchar(10) ) 数据10 ...

  9. 【C语言学习笔记】空间换时间,查表法的经典例子!知识就是这么学到的~

    我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移植性那些角度. 在我们嵌入式中,我们需要根据实际资源的情况来设计我们的代码.比如当我们能用 ...

随机推荐

  1. Kubernetes的Endpoints

    在之前的博文中,我们演示过如何通过ceph来实现kubernetes的持久存储,以使得像mysql这种有状态服务可以在kubernetes中运行并保存数据.这看起来很美妙,然而在实际的生产环境使用中, ...

  2. 微信小程序语音识别

    语音识别现在已经发展的很成熟了,经过比对发现百度对开发者比较友好,提供很多种语言的SDK,对python来说直接安装 pip install baidu-aip 文档写的也不错  具体参考:http: ...

  3. OpenCV---对象测量

    一:获取图像的外接矩形boundingRect和几何距moments import cv2 as cv import numpy as np def measure_object(image): gr ...

  4. "Access restriction: The type BASE64Encoder is not accessible due to restrict"问题解决

    问题如题: Eclipse中有一种叫做存取限制的机制,来防止你错误使用那些非共享的API.通常来说,Eclipse做的是对的,因为两点,我们不想要使用非共享API的,而且Eclipse知道什么是共享的 ...

  5. vee-validate

    http://vee-validate.logaretm.com/ 表单校验,配合VUE使用

  6. zoj 2314 Reactor Cooling (无源汇上下界可行流)

    Reactor Coolinghttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 Time Limit: 5 Seconds ...

  7. dotnet core 实践——日志组件Serilog

     前几天把基于quartz.net的部分项目代码移植到了dotnet core ,但是没增加日志功能,原因是没找到合适的组件. 今天终于找到了Serilog: https://github.com/s ...

  8. 前端开发进阶:推荐的 CSS 书写规范

    写了这么久的CSS,但大部分前端er都没有按照良好的CSS书写规范来写CSS代码,这样会影响代码的阅读体验,这里总结一个CSS书写规范.CSS书写顺序供大家参考,这些是参考了国外一些文章以及我的个人经 ...

  9. JavaScript 数组操作:slice vs splice

    在 JavaScript 中,对于数组的操作有两个很容易混淆的方法 splice, slice ,这里给大家推荐一篇介绍 splice, slice 二者区别的文章. In JavaScript, m ...

  10. Spark 基本架构及原理

    转载自: http://blog.csdn.net/swing2008/article/details/60869183 转自:http://www.cnblogs.com/tgzhu/p/58183 ...