67,513
社区成员
发帖
与我相关
我的任务
分享
package current;
//主类
class TestJMM {
public static void main(String[] args) {
for(int i=0;i<1;i++){
InnerRun jmm=new InnerRun();
jmm.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new InnerStop(jmm).start();
}
}
}
//工作线程
class InnerRun extends Thread{
boolean stop ;
StringBuffer sb=new StringBuffer();
Object lock=new Object();
int i=0;
@Override
public void run() {
while(!stop){
//synchronized(lock){
i++;
//}
}
}
public void stopMe() {
stop = true;
}
}
//停止线程
class InnerStop extends Thread{
InnerRun jmm=null;
public InnerStop(InnerRun jmm){
this.jmm=jmm;
}
@Override
public void run() {
jmm.stopMe();
}
}
public void run() {
while(!stop){
Thread.sleep(1);
}
}
}
这个循环也是能结束的。
我猜测是不是有这样的可能:在循环里读取变量时线程总是从工作内存读,
1.加synchronize或volatile 肯定可以保证同步的。现在我是为了探索在不给变量枷锁的情况下,变量的同步策略。
2.“死循环可能导致stop变量一直没有得到刷新“?为什么?我觉得是因为stop变量没有刷新导致一直死循环
3,我的目录是在没有给变量枷锁的情况下,什么情况下可以看到stop线程的变量?是随机还是什么?你贴出的一段英文是Doug Lea的论文观点,我也是看了他的这个,有点疑惑。我们都知道:读线程要想拿到stop线程变量必须有两步:1,stop线程刷新变量到主内存,2.读线程强制从主内存读取。根据Doug Lea 的观点,我的代码:
public void run() {
while(!stop){
synchronized(lock){
for(int i=1;i<100;i++){
if (Math.log10(i) < 0)
throw new AssertionError();
}
}
}
} 为什么就能读取到stop线程的值,而去掉syncronized就读取不到
[/quote]
看下这个链接
https://help.semmle.com/wiki/display/JAVA/Spin+on+field
class InnerRun extends Thread {
boolean stop;
StringBuffer sb = new StringBuffer();
Object lock = new Object();
int i = 0;
@Override
public void run() {
System.out.println(stop);
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < 2000) { // 这个时间要大于主线程的睡眠时间
}
System.out.println(stop); // 打印出来的是true,当然理论上也不是一定打印true,因为我们说的保证可见性指的是立即可见,但是即使我们不刻意的去保证可见性,它其实最终也是可见的,只不过这个最终的时长是不确定(但往往短到你感觉不出来)而已,实际的运行往往很难测出这种情况
}
public void stopMe() {
stop = true;
}
}
总的来说,while死循环使得stop变量没有机会得到更新
另外,你的这个程序的逻辑就不太对(或许你是刻意这么写的。。),你要保证的是stop变量的可见性,你应该在读写stop变量时加synchronize或者用volatile修饰stop,而不是对i变量的操作加同步