1. 程式人生 > 實用技巧 >執行緒安全相關概念

執行緒安全相關概念

  • 執行緒安全:當多個執行緒訪問某個類時,不管執行時環境採用和種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是執行緒安全的。
  • 競態條件:基於一種可能失效的觀察結果來做出判斷或者執行某個計算。這種型別的競態條件稱為“先檢查後執行”,常見的例子就是i++,以及if(condition) then dosometing。
  • 資料競爭:容易跟競態條件混淆,指如果在訪問共享的非final型別的域時沒有采用同步來協同,那麼就會出現資料競爭,常見於java記憶體模型。
  • 內建鎖,監視器鎖:本質是互斥鎖,Monitor enter,Monitor exit
  • 記憶體可見性:防止某個執行緒正在使用對線狀態而另外一個執行緒在同時修改該狀態,確保當一個執行緒修改了物件狀態後,其他執行緒能夠看到發生的狀態變化。
  • 重排序:以下這段程式碼可能存在重排序問題導致輸出為0。 0.0
  •  1 public class NoVisibility {
     2     private static boolean ready;
     3     private static int number;
     4 
     5     private static class ReaderThread extends Thread {
     6         public void run() {
     
    7 while (!ready) 8 Thread.yield(); 9 System.out.println(number); 10 } 11 } 12 13 public static void main(String[] args) { 14 new ReaderThread().start(); 15 number = 42; 16 ready = true; 17 } 18 }
    View Code
  • 非原子性的64位操作:對於非volatile型別的long和double變數,JVM允許將64位的讀操作或者寫操作分解為兩個32位操作。當讀取一個非volatile型別的long變數時,如果對該變數的讀操作和寫操作在不同的執行緒中,可能讀取的是A的高32位,B的低32位。
  • 如果對不同的鎖進行同步,不能實現執行緒安全
    @NotThreadSafe
    class BadListHelper <E> {
        public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    
        public synchronized boolean putIfAbsent(E x) {
            boolean absent = !list.contains(x);
            if (absent)
                list.add(x);
            return absent;
        }
    }
    
    @ThreadSafe
    class GoodListHelper <E> {
        public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    
        public boolean putIfAbsent(E x) {
            synchronized (list) {
                boolean absent = !list.contains(x);
                if (absent)
                    list.add(x);
                return absent;
            }
        }
    }
    View Code