java thread volatile

黑白地带 发布于 2017/07/30 11:20
阅读 88
收藏 0

首先贴出代码:

package com.dms.thread;

public class VolatileTest{
	public static void main(String[] args) throws InterruptedException {
		RunThread t = new RunThread();
		t.start();
		Thread.sleep(3000);
		t.setRunning(false);
		System.out.println("isRunning的值被设为false");
	}
}

class RunThread extends Thread{
	private boolean isRunning = true;

	public boolean isRunning() {
		return isRunning;
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}
	
	@Override
	public void run() {
		System.out.println("进入run方法");
		while(isRunning){
//			System.out.println("running");
		}
		System.out.println("线程停止");
	}
}

 程序说明:

这是一个测试线程间数据可见的例子;

1.如果注释掉run方法while里的代码,程序就不会停止,如图:

2,如果在while里把

//			System.out.println("running");

注释去掉;结果如图:

 

我的问题:这是为什么呢?区别就是多出一个打印。从打印结果上依我判断,while里有执行代码isRunning就是可见,没有就是不可见?? 求高人指点下!

加载中
0
黑白地带

如果在isRunning上加上volatile肯定是可见的,设置为false后,while会终止。

0
如比如比
如比如比

注释掉后的处理变得比较“原子”,没有对monitor查询的机会。
         8: aload_0
         9: getfield      #12                 // Field isRunning:Z
        12: ifne          8

从而形成这个线程一直占有对象锁,导致没有拿到锁的线程(t.setRunning(false);)只能等待。
System.out.println的处理中是有synchronized (this)的,这会查询monitor的状态,从而会重新调整。
在循环体加上
            synchronized (this) {
            }
时的字节码信息:
        11: aload_0
        12: dup
        13: monitorenter★
        14: monitorexit★
        15: aload_0
        16: getfield      #12                 // Field isRunning:Z
        19: ifne          11

使用命令:
javap -verbose
jstack

 

黑白地带
厉害!你的分析方法是我现在最缺少的 授之以鱼不如授之以渔 谢谢
返回顶部
顶部