昨天聽了下關於併發相關的分享,本身就下來寫了小demo,想要測試一下,demo以下java
import java.util.concurrent.TimeUnit; public class ThreadTest { public static void main(String[] args) throws InterruptedException { Test1 t = new Test1(); Thread th = new Thread(t); th.start(); TimeUnit.SECONDS.sleep(2); t.change(); System.out.println("has changed"); } } class Test1 implements Runnable { private /**volatile*/ boolean flag = true; int c = 0; @Override public void run() { while (flag) { int a = 1; int b = 1; c = a + b; } System.out.println("c: " + c); System.out.println("end"); } public void change() { this.flag = false; } }
很簡答的一個demo,目的是想測試一下加volatile和不加volatile對線程間通信的影響。感興趣的小夥伴能夠跑一下上面的demo(不加volatile的),看下結果。評論區你們能夠留言,看看有沒有不一樣的結果併發
華麗的分割線*jvm
這裏就不賣關子了,按理論來講,上面的demo不加volatile的狀況,是會陷入死循環的,程序沒法中止。加上volatile之後,因爲解決了可見性問題,使得主線程能夠讀到修改後的flag值,從而使循環中止。
然鵝,神奇的事情發生了,不知道有沒有小夥伴和我同樣,運行上面的demo發現,誒?程序居然本身停了....
當時我第一反應是代碼寫錯了,可是讓身邊的小夥伴看了一下,並運行了一下,和個人結果居然不同!他的就沒有中止.....ide
我甚至一度懷疑是我idea的問題(這之後有BUG不能怪我啊,idea出來背鍋...)
當我冷靜下來,仔細想了想,應該是壞境的問題,排查了一堆有的沒的,又上網上查了些資料,最終將眼光放到了JVM上。
經過java -version看了下版本,有了新的發現:個人jvm居然是32位的,用的居然是默認的Client模式....又上網查了下JVM不一樣模式的差異,發如今對代碼編譯優化上存在差異。
看到這裏爲了驗證一下,我將JVM的模式切換到了Serve進行驗證。從新跑了下demo,果真,他停不下來了,疑惑解決。測試
其實發現是編譯器優化致使的問題時,第一反應是前一段時間剛在《Effective java》這本書中提到的一個叫「提高」的優化。爲了驗證我看了下class反編譯之後的文件,結果並無看到想象中的優化結果......因此這個問題產生的真正緣由,目前尚未定位到,後續有時間還有研究研究優化
感謝你們的時間,歡迎評論區留言寫下本身見解,共同交流ui