System.out.println引发的volatile和synchronize
来源:互联网 发布:淘宝简明英语语法教程 编辑:程序博客网 时间:2024/05/22 04:37
public class RunThread extends Thread { private boolean isRuning = true ; public void setRuning(boolean isRun) { this.isRuning = isRun ; } @Override public void run() { System.out.println("进入run方法了"); while (isRuning) {// System.out.println("正在run=="+isRuning); } System.out.println("线程结束"); } public static void main(String[] args) { try { RunThread runThread = new RunThread() ; runThread.start(); runThread.sleep(1000) ; runThread.setRuning(false) ; } catch (Exception e) { e.printStackTrace(); } }}
前几天遇到这么一个小问题,注释掉代码中的System.out.println()程序就会陷入死循环,不注释就会子线程休眠了1s后顺利的跳出循环,顺利执行完毕,这是一个很简单的程序,引发出的问题却很有意思,所以把问题发生所在的思路(注意不是解决问题)给记录下来
(1)先看第一种情况(没有注释System.out.println):
在main函数中,可以看到子线程初始化并启动,然后睡眠1s,然后在主线程中把子线程的isRuning给设置成了FALSE。
从内存的角度来说,在这个过程中其实发生了很多事情:
子线程初始化的时候,isRuning会初始化在主内存(堆内存),但是每个线程都有自己的工作内存,所以会把变量isRuning从主内存拷贝到子线程,也就是说,子线程中使用的isRuning一直都是副本,而在主线程中把isRuning更新为false,更新在主内存了,子线程的副本一直还是true,所以就造成了死循环,这个也就是线程的可见性的一条体现,这个时候给isRuning加个volatile关键字,就可以线程间分享这个变量
(2)第二种情况(注释System.out.println):
这个情况我想了好久,一开始是以为在While(isRuning)里面做了一些操作而造成的的,但是我改了一下程序
while (isRuning) {// System.out.println("正在run=="+isRuning); i++ ; }
把System.out.println改成 i++ 的自增也是会陷入死循环,后来看了System.out.println的源码
public void println(String x) { synchronized (this) { print(x); newLine(); } }
可以看出这里是加锁synchronized的
而synchronized是做了什么的操作呢
- 获得同步锁;
- 清空工作内存;
- 从主内存拷贝对象副本到工作内存;
- 执行代码(计算或者输出等);
- 刷新主内存数据;
- 释放同步锁。
平常我们只知道synchronize只是获得同步锁,实现多线程的互斥,而忽略了中间的内存的运作,而这个也看出synchronize跟volatile的最大区别:volatile只保证多线程内存的可见性,而synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性
后来又试验了一下,把i++的自增操作加了锁,所以isRuning就变得线程可见,线程就跳出了死循环
while (isRuning) {// System.out.println("正在run=="+isRuning); synchronized (this) { i++ ; } }
- System.out.println引发的volatile和synchronize
- System.out.println和System.err.println的区别
- System.out.println和System.err.println的区别
- system.err.println和system.out.println的区别
- System.out.println和System.err.println的区别
- System.out.println()和out.println()
- System.out.println和System.err.println
- 关于System.out.println和System.out.write的实验
- System.out.write()和System.out.println() 的 区别
- System.out.print和System.out.println的区别
- System.out.println()和System.out.write()的区别
- System.out.write和System.out.println
- System.out.write和System.out.println
- System.out.println()和System.out.write()
- system.out.pintln() 和 system.err.println() 的使用注意
- System.out.println的误解
- android的System.out.println
- System.out.println的快捷键
- 电话打入和打出的区别
- ubuntu 16.04 安装opencv 2.4.13
- CTF隐写术--安女神,我爱你!
- 文章索引~软件美化
- 趣味分析系列 | 女生罩杯型号知多少
- System.out.println引发的volatile和synchronize
- 使用动画的注意事项
- 一个沪漂三年IT青年的感悟
- Windows系统结构图
- 欢迎使用CSDN-markdown编辑器
- 栈
- CSS选择器
- 25个经典的Spring面试问答
- leetcode-19-Remove Nth Node From End of List