Please see the following code
public class TestVolatile {
public static void main(String[] args) throws InterruptedException {
ThreadDemo td = new ThreadDemo();
new Thread(td).start();
Thread.sleep(1);
while(true){
if(td.isFlag()){
System.out.println("------------------");
break;
}
}
}
}
class ThreadDemo implements Runnable {
private boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
flag = true;
System.out.println("flag=" + isFlag());
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
Replace Thread.sleep(1)
with Thread.sleep(1000)
to get the modified value of flag
, which is td .isFlag()
returnstrue
.
Although I have read the concept of Java memory model, I don't know how to explain this code. Who can explain it?
Related questions: What is the working memory of Java multi-threading?
You need to first tell me what your expected effect is? Ask questions clearly
This expectation is not supported by standards. Nothing is done in the code to guarantee that "subthread writes happen-before main thread reads".
sleep(1000)
Seeing the modification later is just a coincidence. If a JVM waits longer for the main thread to see it, or even never lets the main thread see it, it does not violate the specification.Your program should be tested
volatile
关键字的功能。但是 “把Thread.sleep(1)
换成Thread.sleep(1000)
就能获得预期效果” 这样做理解上是不对的。首先,程序中总共有两个线程,主线程(暂称 线程M)和
new Thread(td)
(tentatively called thread T).When writing the value of
Thread.sleep(1)
的时候,线程M 在 1ms 之后,便开始在while(true)
循环中检查td.isFlag()
, due to memory visibility, thread M cannot read the value of flag in thread T in time, so an infinite loop is caused at this time;When writing
toThread.sleep(1000)
, M starts to checktd.isFlag()
in thewhile(true)
loop after 1000ms. code>; but T sets the value ofThread.sleep(1000)
的时候,M 在 1000ms 之后,开始在while(true)
循环中检查td.isFlag()
的值;但是 T 在 200ms 的时候,便将 flag 的值设为true
了,所以,M 在 1000ms 之后检测td.isFlag()
的值肯定是返回true
的,那么第一次判断便会返回true
,产生输出并跳出while(true)
flagtrue
at 200ms, so M detectstd.isFlag()
after 1000ms The value must returntrue
, then the first judgment will returntrue
, generate output and jump out of thewhile(true)
loop.In order for thread M to read the value of flag in thread T in time, flag
keyword:volatile
needs to be modified with thevolatile
will be immediately visible to other threads. Regarding the use of , you can refer to my blog: Java Multithreading (6): Use of volatile keyword 🎜You can refer to the following three codes:
The first one is the same as your situation. Due to the visibility problem of multi-threading, it may cause an infinite loop.
The second is to use
synchronized
to solve this problem. This is good for most work scenarios.synchronized
解决此问题,大多数工作场景用这个好第三个是使用
volatile
The third is to usevolatile
to solve this problem, but this keyword only guarantees visibility. In actual scenarios, the limitations are relatively large, so use it with caution