线程 sleep 问题

backthought 2012-05-11 10:53:46
sleep和yield都不具备同步语义,也就是说编译器在执行sleep或yield方法之前和之后,都没有强制要求同步本地缓存与主存的数据
以下摘自JSL3.0
It is important to note that neither Thread.sleep nor Thread.yield have
any synchronization semantics. In particular, the compiler does not have to flush
writes cached in registers out to shared memory before a call to Thread.sleep or
Thread.yield, nor does the compiler have to reload values cached in registers
after a call to Thread.sleep or Thread.yield.
For example, in the following (broken) code fragment, assume that this.done is a non-volatile
boolean field:
while (!this.done)  
Thread.sleep(1000);

The compiler is free to read the field this.done just once, and reuse the cached value
in each execution of the loop. This would mean that the loop would never terminate, even if
another thread changed the value of this.done.


根据以上说明写了一段代码, 应该是停不了啊,但是3秒后sleep就停掉了,请教

public class Test {

boolean flag = true;

public static void main(String[] args) {
Test t =new Test();
t.test();
t.test2();
}

void test(){
new Thread(){
@Override
public void run() {
try {
sleep(3000);
flag = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}

void test2(){
while (flag){
try {
Thread.sleep(1000);
System.out.println("xxxxx");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


...全文
169 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
wugui414 2012-05-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

The compiler is free to read the field this.done just once


不是must

-------------------
又拿出我的这段代码来了:

Java code
public class Visibility {
private static boolean stop;

public s……
[/Quote]

同理使用volatile修饰stop,
private volatile static boolean stop;
也可保证
java Visibility
java -server Visibility
结果运行一样;

可是请教一下1楼,当不使用volatile修饰的时候,为什么客户端和服务器端的虚拟机运行结果不一样?
求详解,谢
wugui414 2012-05-11
  • 打赏
  • 举报
回复
普通变量不能保证线程间可见性,使用volatile关键词修饰,可保证线程间变量的即时可见性(当你一个线程通过赋值的方式修改了变量的值,能保证在另一个线程中马上得知此变量值已改变)
volatile boolean flag = true;//使用volatile修饰
龙四 2012-05-11
  • 打赏
  • 举报
回复
The compiler is free to read the field this.done just once


不是must

-------------------
又拿出我的这段代码来了:

public class Visibility {
private static boolean stop;

public static void main(String[] args) throws Exception {
new Thread(new Runnable(){
public void run() {
int i = 0;
while(!stop) {
i++;
}
System.out.println("finish loop,i=" + i);
}
}).start();


Thread.sleep(1000);
stop = true;
Thread.sleep(2000);
System.out.println("finish main");
}
}



以上代码分别用一下命令执行看结果(hotspot jvm):
java Visibility
java -server Visibility
qybao 2012-05-11
  • 打赏
  • 举报
回复
上面_JAVA_LANGUAGE_DEBUG环境变量说错了,改成_JAVA_LAUNCHER_DEBUG
set _JAVA_LAUNCHER_DEBUG=0
java Visibility
java -server Visibility
qybao 2012-05-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
引用 1 楼 的回复:

The compiler is free to read the field this.done just once


不是must

-------------------
又拿出我的这段代码来了:

Java code
public class Visibility {
private static boolean stop;

publ……
[/Quote]

volatile定义的变量,不会被拷贝到线程local栈,所以线程每次都是直接操作主存的变量,所以多线程之间能互相知道变量的变化,但是原子性不能保证
而非volatile变量为了提高效率会被拷贝到线程的local栈,线程每次操作的是local的拷贝,当线程进入或退出synchronized块时才会和主存比较而刷新

client模式和server模式装载不同的jvm.dll(可以参见jre路径下的client和server文件夹,也可以设置_JAVA_LANGUAGE_DEBUG环境变量来执行程序查看相关debug信息),也就是说两种模式采用不同的JIT来编译一些热门代码为机器码,不同的JIT进行不同的优化,client模式做了少量的优化(方法内联、去虚拟化、冗余消除),server的模式做了大量的优化(逃逸分析、标量替换、栈上分配同步消除),client模式下,线程不一定把共享变量拷贝到local栈(可以查看相关的缺省option),所以client模式下,1L的例子中,client模式下能正常退出,而server模式下因为没有synchronized,线程每次读取的是local的信息,感知不到共享变量的变化,所以不能正常退出。



龙四 2012-05-11
  • 打赏
  • 举报
回复
这就是LZ最后一段英文想要的结果啊


[Quote=引用 3 楼 的回复:]

引用 1 楼 的回复:

The compiler is free to read the field this.done just once


不是must

-------------------
又拿出我的这段代码来了:

Java code
public class Visibility {
private static boolean stop;

p……
[/Quote]

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧