demo1
package com.entity;
public class Test01 {
private static boolean flag;
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
while(true){
if (flag == !flag) {
System.out.println("==over==");
System.exit(0);
}
}
}
}.start();
Thread.sleep(1);
new Thread() {
@Override
public void run() {
while (true) {
flag = !flag;
}
}
}.start();
}
}
該方式下運行 System.out.println("==over=="); 永遠不會執行進入了死循環
public class Test02 {
private static volatile boolean flag;
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
while(true){
if (flag == !flag) {
System.out.println("==over==");
System.exit(0);
}
}
}
}.start();
Thread.sleep(1);
new Thread() {
@Override
public void run() {
while (true) {
flag = !flag;
}
}
}.start();
}
}
該方式下運行 System.out.println("==over=="); 打印
demo2
public class Test03 {
private static boolean keepRunning=true;
public static void main(String[] args) throws Exception {
new Thread(
@override
public void run{
while (keepRunning){
//System.out.println("========");;
}
}
).start();
Thread.sleep(1000);
keepRunning=false;
}
}
同樣 永遠死循環
public class Test04 {
private static volatile keepRunning=true;
public static void main(String[] args) throws Exception {
new Thread(
@override
public void run{
while (keepRunning){
System.out.println("========");
}
}
).start();
Thread.sleep(1000);
keepRunning=false;
}
}
把注釋打開 System.out.println("========"); 執行程序結束 怎么跟內存不可見對應不上呢?
參見:https://www.cnblogs.com/wenjieyatou/p/6210189.html 是由於 打印語句觸發了happen—before
public class StopThread {
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 (!isStopRequested()) {
i++;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);//1秒
requestStop();
}
}
此種情況下還是始終死循環 因為i++ 沒有觸發happen—before
出現死循環的原因:
java 內存模型(JMM)有主內存和線程的工作內存 關系如下:
1. 線程的工作內存會去讀取主內存的成員變量並保存副本
2. 線程在工作內存中修改副本
3. 將修改后的副本的值推送給主空間並改寫主空間該成員變量的值(線程棧執行完畢后會把副本的值推送給主存)
4. 主空間成員變量修改后的值將不會主動推送給其他線程, 這就造成了線程的工作內存的共享變量的不同步
就是造成上面死循環的原因
如何解決呢?
通過 volatile 解決
Volatile字段主要用於線程之間進行通信,volatile字段的每次讀行為都能看到其它線程最后一次對該字段的寫行為,所以共享變量的數據是最新的
參考文章:
http://www.cnblogs.com/huangleshu/p/10026222.html
https://baijiahao.baidu.com/s?id=1595082600371869908&wfr=spider&for=pc
static 是內存中的唯一份共享變量 volatile 也是內存唯一份的內存可見 那么二者有和區別呢?
1. volatile是告訴編譯器,每次取這個變量的值都需要從主存中取,而不是用自己線程工作內存中的緩存.
2. static 是說這個變量,在主存中所有此類的實例用的是同一份,各個線程創建時需要從主存同一個位置拷貝到自己工作內存中去(而不是拷貝此類不同實例中的這個變量的值),
也就是說只能保證線程創建時,變量的值是相同來源的,運行時還是使用各自工作內存中的值,依然會有不同步的問題.
參考:http://www.cnblogs.com/cvbaka/p/4764503.html