synchronized另一层被忽略的含义

来源:互联网 发布:网络小说排行榜 知乎 编辑:程序博客网 时间:2024/06/08 16:24

这是一次关于volatile关键字的探索,在这次探索中我学习到了synchronized关键字的另外一层含义,事情经过是这样的:首先有我从网上找的这一段代码,用来体现一个变量加volatile关键字和不加volatile关键字的区别。在这段代码中,如果不给"isRunning"加上volatile修饰,则运行程序,发现有个线程一直在运行;如果加上volatile修饰,则程序可以顺利执行完成。这是因为不加volatile的“Running”变量,在线程RunThread执行时使用的是工作副本,所以结果是该线程体会一直执行下去;而当加上了volatile修饰后,“isRunning” 每次在被使用的时候应该都是从主内存中获取数据,这种情况下,当main线程修改“isRunning”  为false的时候。RunThread线程体就会立即看到这个改变,从而导致线程体停止。 这就是volatile使得被其修饰的变量在线程之间变得可见的原因吧。后来不知道有什么疑惑,我就在RunThread线程体的循环内加了一句System.out.println("aaa")。这时候奇怪的事情发生了,当我再次运行这个程序,发现RunThread结束了!难道在没有volatile修饰的时候,循环体不结束的原因仅仅是因为循环体内没有代码?!然后我又尝试着在循环体内只加“i++;”,结果程序又没停止!难道是操作太简单?于是乎我又只加了"new Object();",结果程序还是没停止。郁闷了。。,难道System.out.println("aaa")还有神奇的保证可见性的功效?!如此奇怪,只能网上找找大神的答案了,是有人碰到了类似的事儿,但是给出的答案好像都似是而非。比如有人说是因为System.out.println("aaa")是同步方法,所以导致了好像叫做“粗粒度锁”的优化,相当于给“isRunning”做了同步,还能这么说么,,我想说,main主线程改变“isRunning”值的set方法可并没有加锁啊。最终看到有人说synchronized除了有实现互斥访问之外,还有另一层被忽略的含义,即实现本线程工作副本和主内存的同步!确实是这样么,于是乎我在RunThread中的循环体这种只放了synchronized ("aaaa") {},然后再运行程序,发现程序正常结束了!基本上可以看到线程中的同步快确实是有这样的作用,也就解释了循环体中只有“System.out.println("aaa");”可以使得RunThread停止的原因。

public class RunThread extends Thread{

private  boolean isRunning = true;
private void setRunning(boolean isRunning){
this.isRunning = isRunning;
}
public void run(){
System.out.println("进入run方法..");
int i = 0;
while(isRunning == true){


}
}
public static void main(String[] args) throws InterruptedException {
RunThread rt = new RunThread();
rt.start();
Thread.sleep(1000);
rt.setRunning(false);
System.out.println("isRunning的值已经被设置了false");
System.out.println(rt.isRunning);
}
}
原创粉丝点击