TreeMap 和 TreeSet 執行緒安全
TreeMap
和 TreeSet
不是執行緒安全的集合,因此必須注意確保在多執行緒程式中使用時。
TreeMap
和 TreeSet
在多執行緒讀取時都是安全的,甚至是同時讀取的。因此,如果它們是由單個執行緒建立並填充的(例如,在程式的開頭),然後只讀,但不被多個執行緒修改,則沒有理由進行同步或鎖定。
但是,如果同時讀取和修改,或者由多個執行緒同時修改,則集合可能會丟擲 ConcurrentModificationException 或意外行為。在這些情況下,必須使用以下方法之一同步/鎖定對集合的訪問:
-
使用
Collections.synchronizedSorted..
:SortedSet<Integer> set = Collections.synchronizedSortedSet(new TreeSet<Integer>()); SortedMap<Integer,String> map = Collections.synchronizedSortedMap(new TreeMap<Integer,String>());
這將提供由實際集合支援的 SortedSet / SortedMap 實現,並在某些互斥物件上進行同步。請注意,這將在單個鎖上同步對集合的所有讀寫訪問許可權,因此即使是併發讀取也是不可能的。
-
通過手動同步某個物件,如集合本身:
TreeSet<Integer> set = new TreeSet<>();
…
//Thread 1 synchronized (set) { set.add(4); }
…
//Thread 2 synchronized (set) { set.remove(5); }
-
通過使用鎖,例如 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 允許多個執行緒同時從對映中讀取。