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是做了什么的操作呢

  1. 获得同步锁;
  2. 清空工作内存;
  3. 从主内存拷贝对象副本到工作内存;
  4. 执行代码(计算或者输出等);
  5. 刷新主内存数据;
  6. 释放同步锁。

平常我们只知道synchronize只是获得同步锁,实现多线程的互斥,而忽略了中间的内存的运作,而这个也看出synchronize跟volatile的最大区别:volatile只保证多线程内存的可见性,而synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性
后来又试验了一下,把i++的自增操作加了锁,所以isRuning就变得线程可见,线程就跳出了死循环

        while (isRuning) {//          System.out.println("正在run=="+isRuning);            synchronized (this) {                i++ ;            }        }
0 0
原创粉丝点击