最近在編寫項目的時候使用while遇到了一個奇怪的問題。我在使用異步調用的時候主線程某一個方法須要等待異步返回才能被調用,所以我設定了一個boolean,當異步返回時修改條件而後在主線程的方法中加入while來長時間遍歷以等待異步返回。java
這裏我將代碼省略只保留主要:異步
public static void main(String[] args) {
Task task = new Task();
new Thread(task).start();
try {
Thread.sleep(3000);
} catch (Exception e) {}
task.close();
}
class Task implements Runnable {
private int i = 1;
public void run() {
while (i == 1){}
System.out.println("跳出循環");
}
public void close() {
i = 2;
}
}
複製代碼
Task啓動後會在while中死循環,主線程等待3s後將i修改爲2,可是task中的while沒有跳出,即 i == 1 條件仍是爲true。spa
其中的while換成for,do-while都是同樣的結果線程
經過詢問他人,雖然沒有弄明白髮生的緣由。可是他提出了一個解決辦法。code
在程序中內存
while(i == 1){}
複製代碼
會過多佔用CPU,所以使用Thread.yield()來將CPU資源讓步給其餘線程。當while中加入這個以後就能達到我須要的效果了。資源
更新: Java內存模型規定:同步
這三點直接就點名了錯誤的緣由。解決辦法有兩個:string
volatile關鍵字:
volatile語意:it
缺點:volatile只能保證線程的變量可見性。可是它沒有鎖機制,因此沒法避免多個線程同時訪問公共變量。
優勢:編寫簡單。
synchronized關鍵字
synchronized語意:
優勢:有加鎖機制,保護共享資源。
Java內存協議規定了8中原子操做:
這些操做都是原子性,可是操做之間不是原子性。