다음 코드를 참고해주세요
으아악넣어Thread.sleep(1)
换成Thread.sleep(1000)
就能获取flag
修改后的值,即td.isFlag()
返回true
.
Java 메모리 모델의 개념을 읽었지만 이 코드를 어떻게 해석해야 할지 모르겠습니다. 누가 설명할 수 있나요?
관련 질문: Java 멀티스레딩의 작업 메모리는 무엇인가요?
滿天的星座2017-05-17 10:08:58
이러한 기대는 표준에 의해 뒷받침되지 않습니다. "메인 스레드를 읽기 전에 하위 스레드 쓰기가 발생합니다"를 보장하기 위해 코드에서는 아무 작업도 수행되지 않습니다.
sleep(1000)
나중에 수정 사항을 보는 것은 단지 우연일 뿐입니다. JVM이 메인 스레드가 이를 볼 때까지 더 오래 기다리거나 심지어 메인 스레드가 이를 볼 수 없도록 허용하는 경우에도 사양을 위반하지 않습니다.
怪我咯2017-05-17 10:08:58
프로그램은 휘발성
키워드의 기능을 테스트해야 합니다. 그러나 "Thread.sleep(1)
을 Thread.sleep(1000)
으로 바꾸면 원하는 효과를 얻을 수 있습니다"는 올바른 이해가 아닙니다.
우선 프로그램에는 두 개의 스레드가 있습니다. 메인 스레드(가칭 스레드 M이라고 함)와 new Thread(td)
(가칭 스레드 T라고 함)입니다. volatile
关键字的功能。但是 “把 Thread.sleep(1)
换成 Thread.sleep(1000)
就能获得预期效果” 这样做理解上是不对的。
首先,程序中总共有两个线程,主线程(暂称 线程M)和 new Thread(td)
(暂称 线程T)。
当写 Thread.sleep(1)
的时候,线程M 在 1ms 之后,便开始在 while(true)
循环中检查 td.isFlag()
的值,但是因为内存可见性的关系,线程M 并不能及时读取 线程T 中 flag 的值,所以此时导致了死循环;
当写 Thread.sleep(1000)
的时候,M 在 1000ms 之后,开始在 while(true)
循环中检查 td.isFlag()
的值;但是 T 在 200ms 的时候,便将 flag 的值设为 true
了,所以,M 在 1000ms 之后检测 td.isFlag()
的值肯定是返回 true
的,那么第一次判断便会返回 true
,产生输出并跳出 while(true)
循环。
为了让 线程M 及时读取到 线程T 中 flag 的值,需要将 flag 使用 volatile
关键字进行修饰:
private volatile boolean flag = false;
那么每次对 flag 的修改,其他线程都立马可见。关于 volatile
<시간>
Thread.sleep(1)
을 작성할 때 스레드 M은 1ms 후 while(true)
루프에서 td.isFlag() 검사를 시작합니다. 그러나 메모리 가시성으로 인해 스레드 M은 스레드 T의 플래그 값을 적시에 읽을 수 없으므로 이때 무한 루프가 발생합니다. 🎜
<시간>
🎜Thread.sleep(1000)
을 작성할 때 M은 1000ms 후에 while(true)
루프에서 td.isFlag()
를 확인하기 시작합니다. code>; 그러나 T는 200ms에서 flag 값을 true
로 설정하므로 M은 td.isFlag( 1000ms 이후 )
를 감지하여 true
이면 첫 번째 판단은 true
를 반환하고 출력을 생성하며 while(true)
code> 루프에서 빠져나옵니다. 🎜
<시간>
🎜스레드 M이 스레드 T의 flag 값을 적시에 읽으려면 flag를 휘발성
키워드로 수정해야 합니다. 🎜
으아아아
🎜그러면 플래그에 대한 모든 수정 사항이 즉시 다른 스레드에 표시됩니다. 휘발성
사용에 대해서는 내 블로그인 Java Multithreading (6): Use of the 휘발성 키워드 🎜를 참조하세요.회신하다0
大家讲道理2017-05-17 10:08:58
다음 3가지 코드를 참고하시면 됩니다.
첫번째는 멀티스레딩의 가시성 문제로 인해 무한루프가 발생할 수 있는 상황입니다.
두 번째는 이 문제를 해결하기 위해 synchronized
를 사용하는 것입니다. synchronized
解决此问题,大多数工作场景用这个好
第三个是使用volatile
세 번째는 이 문제를 해결하기 위해 휘발성
을 사용하는 것입니다. 실제 시나리오에서는 제한이 상대적으로 크기 때문에 주의해서 사용하세요