Если коллекцию пометить volatile можно ли сказать, что запись\удаление\чтение объектов будут выполняться в ней всегда атомарно?
Предположим я создал коллекцию
volatile ArrayList <Integer> vo_al = new ArrayList<>();
Вопрос: Можно ли быть увереным, что когда я создам 100 потоков, которые будут читать и записывать туда значения, что потоки не попортят друг-другу память, а изменения которые внесёт один поток операцией
vo_al.add(2);
будут сразу видны всем другим потокам?
Есть ли в принципе смысл, в многопоточном программировании помечать коллекции словом volatile?
Ответы (1 шт):
Конечно же нет. volatile никак не связан с объектом, который лежит по ссылке, он гарантирует, что запись и чтение переменной будет атомарно (насколько я знаю, не атомарными по записи и чтению являются только long и double) и что изменения переменной (изменение именно ссылки! а не какие-либо методы вроде add) будут сразу же видны другим потокам.
Если вам нужно безопасно изменять List в нескольких потоках, то используйте Collections.synchronizedList:
List<Integer> vo_al = Collections.synchronizedList(new ArrayList<>());
Но и это не означает, что не понадобится synchronized блок или другие методы синхронизации.
Например, нужно атомарно увеличить первый элемент списка на единицу. Даже с synchronizedList нужно использовать synchronized блок, так как происходит две разные операции, между которыми поток может быть остановлен или в этот момент времени произошло изменение значения из другого потока.
synchronized (vo_al) {
vo_al.set(0, vo_al.get(0) + 1));
}
Есть ли в принципе смысл, в многопоточном программировании помечать коллекции словом volatile?
Есть, если в каком-то потоке происходит изменение ссылки.
volatile ArrayList <Integer> vo_al = new ArrayList<>();
// в одном из потоков
vo_al = new ArrayList<>();