Java SE 多線程安全問題產生的原因?
問題描述
可能像圖片上的代碼出現(xiàn)負數的概率不大,但在if語句后加上Thread.sleep(10);就能看到輸出負數
問題解答
回答1:不知道你要問什么,多個線程同時讀取一個資源出現(xiàn)不同步問題很正常,因為可能一個線程獲取值的時候另一個線程恰好在寫值,這就會產生同步問題。
解決辦法有很多,最笨的直接代碼塊上加同步,整個鎖起來;好點的是用線程安全的類,比如AtomInteger這種,保證同步;如果對多線程很有研究,甚至可以只加很少的鎖就能完成任務。
回答2:線程的調用順序是不保證有序的,其根本原因在于JVM協(xié)調資源時線程之間的切換。
回答3:本質原因是CPU為了提高效率會對指令進行重排序
回答4:沒有對num進行同步,不能保證當前線程對num的值改之后,其他線程可以立馬看到,題主可以了解下Java內存模型。 以題主的代碼為例,假設執(zhí)行到最后num=1,三個線程同時執(zhí)行到if判斷,都能判斷出通過,那就有可能出現(xiàn)負數。
回答5:1、內存可見性2、修改的原子性
由于num是類靜態(tài)變量,那么它會被存到堆中,在run()方法執(zhí)行時拷貝一份副本到棧中存儲,當有多個線程修改時,可能同時拿到一樣的副本,但是由于執(zhí)行的前后順序,一個線程修改并寫入了該變量,雖然堆中num已經發(fā)生變化,但是其他線程并不知道,它們會繼續(xù)修改那份副本。然后修改后寫入堆中,那這樣就會覆蓋之前線程的修改,進而導致狀態(tài)的不一致問題。那么如果才能確保線程安全性呢。那就要確保修改num之前保證對堆區(qū)修改的可見性,修改之前再拿一份副本(即使之前已經拿過了),這個可用volatile關鍵字來保證。
原子性,由于num--實際執(zhí)行是兩個操作,那么就會存在執(zhí)行順序問題。即使在前面說過用volatilel來保證可見性。但是還會存在修改被其他線程覆蓋的情形,只不過幾率變小了。怎樣保證原子性呢,可以采用synchronized關鍵字,Lock機制,以及JDK并發(fā)工具包等。對于這種情形,最簡單的辦法就是
private static AtomicInteger num=new AtomicInteger(100);
相關文章:
1. 數組排序,并把排序后的值存入到新數組中2. html5 - css3scale和rotate同時使用轉換成matrix寫法該如何轉換?3. mysql 遠程連接出錯10060,我已經設置了任意主機了。。。4. 默認輸出類型為json,如何輸出html5. 為何 localStorage、sessionStorage 屬于html5的范疇,但是為何 IE8卻支持?6. MySQL的聯(lián)合查詢[union]有什么實際的用處7. python的正則怎么同時匹配兩個不同結果?8. PHP訂單派單系統(tǒng)9. php多任務倒計時求助10. win10 python3.5 matplotlib使用報錯
