Если коллекцию пометить volatile можно ли сказать, что запись\удаление\чтение объектов будут выполняться в ней всегда атомарно?

Предположим я создал коллекцию

volatile ArrayList <Integer> vo_al = new ArrayList<>();

Вопрос: Можно ли быть увереным, что когда я создам 100 потоков, которые будут читать и записывать туда значения, что потоки не попортят друг-другу память, а изменения которые внесёт один поток операцией

vo_al.add(2);

будут сразу видны всем другим потокам?

Есть ли в принципе смысл, в многопоточном программировании помечать коллекции словом volatile?


Ответы (1 шт):

Автор решения: IR42

Конечно же нет. volatile никак не связан с объектом, который лежит по ссылке, он гарантирует, что запись и чтение переменной будет атомарно (насколько я знаю, не атомарными по записи и чтению являются только long и double) и что изменения переменной (изменение именно ссылки! а не какие-либо методы вроде add) будут сразу же видны другим потокам.

Atomic Access

Если вам нужно безопасно изменять 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<>();
→ Ссылка