volatile修飾全局變量,可以保證線程並發安全嗎?


 

今天被人問到volatile能不能保證並發安全?

呵,這能難倒我?

上代碼:(代碼太長建議跳到頁末)

//電腦太好,100線程起步~
public class ThreadTest { private static volatile int num = 0; public static void main(String[] args) throws InterruptedException { new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); Thread.sleep(500); System.out.println(num); } }

期望最終值:
  100 * 100 = 10000

輸出結果:
  ...
  ...
  9998
  9998
 

分析:

  100個線程對volatilei修飾的num++,會被編譯成以下三步:
   1.獲取i的值;2.執行i+1;3.將結果賦值給i。
  volatile只能保證可見性,並不能保證原子性。

結論:
  volatile只能保證這3步在編譯后指令不會被重新排序,並不能保證線程並發的數據安全。建議搭配上synchronized或其他Lock鎖使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM