/**
* This is description.
* 下面这段文字解释来自马士兵老师:
*
* volatile关键字: 使得线程之间具有可见性, 从而进行缓存过期通知.
* A B线程都用到一个变量,java默认是A线程中保留一份copy,这样如果B线程修改了该变量,则A线程未必知道
* 使用volatile关键字,会让所有线程都会读到变量的修改值
*
* 在下面的代码中,running是存在于堆内存的t对象中
* 当线程t1开始运行的时候,会把running值从内存中读到t1线程的工作区,在运行过程中直接使用这个copy,并不会每次都去
* 读取堆内存,这样,当主线程修改running的值之后,t1线程感知不到,所以不会停止运行
*
* 使用volatile,将会强制所有线程都去堆内存中读取running的值
*
* 可以阅读这篇文章进行更深入的理解.(画图解释)
* http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.html
*
* volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized.
* @author Chris Lee
* @date 2019/3/5 22:10
*/
public class Demo {
volatile boolean running = true;
private void fun() {
System.out.println("当前线程为" + Thread.currentThread().getName() + ": start!");
while (running) {
///
/*
try {
TimeUnit.MICROSECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
}
System.out.println("当前线程为" + Thread.currentThread().getName() + ": end!");
}
public static void main(String[] args) {
Demo demo = new Demo();
new Thread(demo::fun, "t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 给running进行赋值
demo.running = false;
/*
1) 没有volatile修饰running时, 打印结果:
当前线程为t1: start!
2) 有volatile修饰running时, 打印结果:
当前线程为t1: start!
当前线程为t1: end!
*/
}
}
说明:
- 本篇文章如有不正确或待改进的地方, 欢迎批评和指正, 大家一同进步, 谢谢!
- 世上有4样东西可以让世界变得更美好, 它们是: 代码(Code), 诗(Poem), 音乐(Music), 爱(Love). 如有兴趣了解更多, 欢迎光顾"我的文集"相关文章.
资料:
- 学习视频: https://www.bilibili.com/video/av11076511/?p=1
- 参考代码: https://github.com/EduMoral/edu/tree/master/concurrent/src/yxxy
- 我的代码: https://github.com/ChrisLeejing/learn_concurrency.git