并发--Effective Java的一小段代码

本文探讨了一个Java程序在Eclipse IDE中的行为与Effective Java书籍描述之间的差异,重点在于线程停止机制和volatile关键字如何影响线程执行顺序。通过分析线程循环条件的不确定性,解释了在不使用volatile关键字时程序可能无限循环的原因,并说明了volatile关键字如何确保线程间正确同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


import java.util.concurrent.TimeUnit;

/**
* @author gl65293
*
*/
public class StopThread {

/**
* @param args
*/

private static boolean stopRequested;

public static void main(String[] args) throws InterruptedException {

Thread backgroundThread = new Thread(new Runnable(){
public void run(){
int i = 0;
while(!stopRequested){
i++;
}
}
});

backgroundThread.start();

TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}

}

在Effective Java 中文版 第二版的230页,说的是这个程序不会停下来. 可你把这个程序放入到eclipse这种ide里去执行的时候,你却发现在很多时候,这个程序都会在执行1秒后停下来. 为什么呢? 这个怎么跟书上说的不一样?

其实, 书上跟自己的实践都是对的, 在eclipse ide里执行这个程序里, 你要加上 -server参数, 这个程序运行就不会停下来了.

这是为什么呢?
因为在加上 -server参数后, jvm会对执行顺序进行优化.

解释如下:
backgroundThread什么时候退出循环是不能确定的,有可能1秒后就退出了,也有可能永远不会退出。程序执行时有如下2中可能情况:
第一种可能,由于stopRequested没有同步或者volatile修饰,jvm为了加快线程的执行速度,每个线程都会对stopRequested做变量拷贝,这时候对变量的修改可能就不会或者不能够及时同步到每个线程中,这种情况backgroundThread 线程什么时候执行结束是不能确定的,>=1秒后结束,或者永远不会结束都有可能。

第二种可能,jvm会对

while(!stopRequested){
i++;
}



做优化,优化后程序执行流程变为

if(!stopRequested) {
while(true){
i++;
}
}


,这种情况,backgroundThread线程永远不会结束。

为了避免以上两种情况,可以用volatile修饰stopRequested,这样每个线程在修改stopRequested后都会把修改结果同步到主内存,每个线程在读取stopRequested时都会从主内存中获取;volatile同时也阻止了jvm对第二种情况的优化

建议细看: 《java并发编程实践》

注:
[color=red]在不加 volatile修饰, 把i++改成System.out.println("t"); 的情况下, 使用-server, -client参数都会在1秒后退出. [/color]

在windows下,jvm默认是client模式, 在linux下默认是 server模式.

参考:
[url=http://www.iteye.com/topic/875420]Java线程安全兼谈DCL[/url]
[url=http://www.iteye.com/topic/260515]用happen-before规则重新审视DCL[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值