Какие все коллекции Java синхронизированы и не синхронизированы
Какие все коллекции Java синхронизированы и не синхронизированы
Пример: HashSet не синхронизирован
11 ответов
Коллекции безопасных ниток -
- ConcurrentHashMap
Потокобезопасен без синхронизации всей карты. Очень быстрое чтение, в то время как запись выполняется с блокировкой. Нет блокировки на уровне объекта. Использует множество блокировок.
- SynchronizedHashMap
Синхронизация на уровне объекта. И чтение, и запись получают блокировку. Блокировка коллекции имеет недостаток производительности. Может вызвать конфликт
Вектор
Хеш-таблица
CopyOnWriteArrayList
CopyOnWriteArraySet
стек
Все остальное не безопасно
Есть три группы коллекций.
- Java 1.0 коллекции, которые в основном унаследованные классы. Это включает в себя Hashtable, Vector, Stack. Они синхронизированы, но я не рекомендую их использовать. Свойства, пожалуй, одно исключение, но я бы не стал использовать его в многопоточном контексте.
- Коллекции Java 1.2, добавленные в 1998 году, которые в значительной степени заменили эти коллекции, не синхронизированы, но могут быть синхронизированы с помощью
Collections.synchronizedXxx()
методы - Коллекции параллелизма Java 5.0, добавленные в 2004 году, поддерживают коллекции без блокировок, безопасные для потоков.
Короче говоря, ни одна из коллекций, которые я бы порекомендовал вам использовать, не синхронизирована.
Вы можете получить синхронизированную версию Java Collection
с
Collections.synchronizedCollection(Collection<T> c)
[ Javadoc]
Простой ответ: ни одной реализации Collection
синхронизируется, потому что synchronized
не является свойством класса, оно применимо только к методам и блокам.
Полагаю, вы хотите знать, какие реализации являются поточно-ориентированными, какие классы из инфраструктуры java collection можно безопасно использовать в многопоточной среде.
Информация всегда включена в javadoc ( как здесь: Arraylist - который не является потокобезопасным)
ArrayList, LinkedList, HashSet,LinkedHashset и TreeSet в интерфейсе коллекции, а также HashMap,LinkedHashMap и Treemap не синхронизированы.
Вектор в интерфейсе коллекции синхронизирован
- Наследие -
Vector
(родительList
) иHashtable
(родительMap
) - Синхронизированные коллекции используют
synchronized
монитор.Collections.synchronized
,Collections.synchronizedList()
,Collections.synchronizedSortedMap()
,Collections.synchronizedSet()
... - Параллельные коллекции (Java 5)
-
Copy-On-Write(COW)
- имеет лучшую производительность, чем синхронизированные коллекции, но требует большего объема памяти. Новая копия массива создается при его изменении (добавлении, установке, удалении). Это хороший вариант для операций многократного чтения и модификации задней части.CopyOnWriteArrayList
,CopyOnWriteArraySet
-
Compare-And-Swap(CAS)
<sup>[О]</sup> -ConcurrentLinkedQueue
,ConcurrentSkipListMap
-
Lock
основан -ConcurrentHashMap
,BlockingQueue
потомки
-
Все классы коллекций (кроме Vector и Hashtable) в пакете java.util не являются поточно-ориентированными. Только две старые коллекции являются поточно-ориентированными: Vector и Hashtable. ЗАЧЕМ? Вот причина: синхронизация может быть очень дорогой! Вы знаете, Vector и Hashtable - это две коллекции, которые существуют на ранних этапах истории Java, и они с самого начала разработаны для поточной защиты (если у вас есть возможность взглянуть на их исходный код, вы увидите, что все их методы синхронизированы!). Однако они быстро показывают низкую производительность в многопоточных программах. Как вы, возможно, знаете, синхронизация требует блокировок, для мониторинга которых всегда требуется время, что снижает производительность. Вот почему новые коллекции (List, Set, Map и т. Д.) Вообще не обеспечивают управление параллелизмом, чтобы обеспечить максимальную производительность в однопоточных приложениях.
Предыдущий пример совершенно неверен.
Прежде всего, вы не получаете доступ из разных потоков к списку, который вы только что синхронизировали, у вас нет доказательств того, что синхронизация выполняется правильно, вы не можете доказать, что процесс добавления является атомарным. Во-вторых, предложение о синхронизации по всему списку - плохая практика, вы не знаете, будет ли оптимизатор использовать элемент в списке для синхронизации, что приведет к неожиданному поведению. Кроме того, вы синхронизируете доступ к элементам в списке для чтения / записи, а не к самому списку. Выньте Collections.synchronized и посмотрите вывод. Попробуйте много раз. Пожалуйста, возьмите следующий пример:
class ProcessSomething {
private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
private void calculate() {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
integerList.add(new Random().nextInt(100));
}
}
private void calculate2() {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
integerList.add(new Random().nextInt(100));
}
}
public void process() {
Long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable() {
public void run() {
calculate();
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
calculate2();
}
});
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException ex) {
Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
}
Long end = System.currentTimeMillis();
System.out.println("Duration: " + (end - start));
System.out.println("List size: " + integerList.size());
}
}
public class App {
public static void main(String[] args) {
new ProcessSomething().process();
}
}
Синхронизация делает производительность ниже. Конечно, коллекция Java не синхронизирована. но в Java предусмотрены оболочки синхронизации для синхронизации коллекции Java см. ссылку
for example:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
syncList.add("one");//no need to synchronize here
syncList.add("two");
syncList.add("three");
String st = syncList.get(0); //it is ok here => no need to synchronize
// when iterating over a synchronized list, we need to synchronize access to the synchronized list
//because if you don't synchronize here, synchList maybe be changed during iterating over it
synchronized (syncList) {
Iterator<String> iterator = syncList.iterator();
while (iterator.hasNext()) {
System.out.println("item: " + iterator.next());
}
}
}
}
Import java.util.Collections; // Импортируем это
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
Вот как вы можете синхронизировать список в java.
Я предполагаю, что каждая реализация API коллекции написана в документации.