TreeMap 和 TreeSet 執行緒安全

TreeMapTreeSet 不是執行緒安全的集合,因此必須注意確保在多執行緒程式中使用時。

TreeMapTreeSet 在多執行緒讀取時都是安全的,甚至是同時讀取的。因此,如果它們是由單個執行緒建立並填充的(例如,在程式的開頭),然後只讀,但不被多個執行緒修改,則沒有理由進行同步或鎖定。

但是,如果同時讀取和修改,或者由多個執行緒同時修改,則集合可能會丟擲 ConcurrentModificationException 或意外行為。在這些情況下,必須使用以下方法之一同步/鎖定對集合的訪問:

  1. 使用 Collections.synchronizedSorted..

    SortedSet<Integer> set = Collections.synchronizedSortedSet(new TreeSet<Integer>());
    SortedMap<Integer,String> map = Collections.synchronizedSortedMap(new TreeMap<Integer,String>());
    

    這將提供由實際集合支援的 SortedSet / SortedMap 實現,並在某些互斥物件上進行同步。請注意,這將在單個鎖上同步對集合的所有讀寫訪問許可權,因此即使是併發讀取也是不可能的。

  2. 通過手動同步某個物件,如集合本身:

     TreeSet<Integer> set = new TreeSet<>(); 
    

    //Thread 1
    synchronized (set) {
        set.add(4);
    }
    

    //Thread 2
    synchronized (set) {
        set.remove(5);
    }        
    
  3. 通過使用鎖,例如 ReentrantReadWriteLock

     TreeSet<Integer> set = new TreeSet<>(); 
     ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    

     //Thread 1
     lock.writeLock().lock();
     set.add(4);
     lock.writeLock().unlock();
    

     //Thread 2
     lock.readLock().lock();
     set.contains(5);
     lock.readLock().unlock();
    

與之前的同步方法相反,使用 ReadWriteLock 允許多個執行緒同時從對映中讀取。