Просто уточняйте ответ с помощью некоторого кода источника.
http://www.docjar.com/html/api/java/util/Collections.java.html
1) Да, это коллекция обертка (экземпляр частного статического класса SynchronizedSet
), как указано в line 2054
из Collections
кода класса.
2051 public Set<K> keySet() {
2052 synchronized (mutex) {
2053 if (keySet==null)
2054 keySet = new SynchronizedSet<>(m.keySet(), mutex);
2055 return keySet;
2056 }
2057 }
Обратите внимание, что этот SynchronizedSet использует тот же семафор, который SynchronizedMap, возвращенное Collections.synchronizedMap(new HashMap());
использует.
2) Необходимо синхронизировать его на m вместо s, потому что все операции в возвращаемом наборе (SynchronizedSet) в Set s = m.keySet();
синхронизируются на одном и том же мьютексе (возвращена Синхронизированная карта), но не на возвращенном наборе. Это можно увидеть из следующих точек:
a) Все операции в Map (SynchronizedMap), возвращаемые Collections.synchronizedMap(new HashMap());
, синхронизируются по возвращенной карте iteslf как мьютексу, как видно из следующих строк кода, как видно из строк 2004,2010,2035. :
1992 public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
1993 return new SynchronizedMap<>(m);
1994 }
SynchronizedMap класс определяется как:
1999 private static class SynchronizedMap<K,V>
2000 implements Map<K,V>, Serializable {
2001 ...
2002
2003 private final Map<K,V> m; // Backing Map
2004 final Object mutex; // Object on which to synchronize
...
SynchronizedMap(Map<K,V> m) {
2007 if (m==null)
2008 throw new NullPointerException();
2009 this.m= m;
2010 mutex = this;
2011 }
...
2034 public V put(K key, V value) {
2035 synchronized (mutex) {return m.put(key, value);}
2036 }
...
}
б) когда мы итерация карты, Iterator i = s.iterator();
мы должны синхронизировать его на т вместо й, так как операции в возвращаемой Set (SynchronizedSet) в Set s = m.keySet();
синхронизируются же мьютекса (возвращается Синхронное карте), но не на с, как показано в строке 2054.
2051 public Set<K> keySet() {
2052 synchronized (mutex) {
2053 if (keySet==null)
2054 keySet = new SynchronizedSet<>(m.keySet(), mutex);
2055 return keySet;
2056 }
2057 }
для (1) означает, что установленный набор будет работать так же, как Collections.synchronizedSet (...). Для (2) см. Править. –
Нет, это не так, как если бы вы получили его из synchronizedSet, потому что когда он синхронизирует его, он блокирует родительскую карту, а не сам по себе. – Affe