Члены ArrayList
не защищены какими-либо барьерами памяти, поэтому нет гарантии, что их изменения видны между потоками.Это применимо даже в том случае, если единственное «изменение», которое когда-либо вносилось в список, - это его конструкция.
Любые данные , которые совместно используются потоком, нуждаются в «барьере памяти», чтобы обеспечить его видимость.Есть несколько способов сделать это.
Во-первых, любой член, объявленный final
и инициализированный в конструкторе, виден любому потоку после его завершения.
Изменения любого члена, объявленного volatile
, виднывсе темы.По сути, запись «сбрасывается» из любого кэша в основную память, где ее может видеть любой поток, обращающийся к основной памяти.
Теперь она становится немного сложнее.Любые записи, сделанные потоком до , которые поток записывает в переменную переменной, также сбрасываются.Аналогично, когда поток считывает энергозависимую переменную, его кэш очищается, и последующие чтения могут снова заполнить его из основной памяти.
Наконец, блок synchronized
подобен энергозависимому чтению и пиши, с добавленным качеством атомности.Когда монитор получен, кэш чтения потока очищается.Когда монитор освобождается, все записи сбрасываются в основную память.
Один из способов выполнить эту работу - заставить поток, который заполняет вашу общую структуру данных, присвоить результат переменной volatile
(илиAtomicReference
или другой подходящий java.util.concurrent
объект).Когда другие потоки обращаются к этой переменной, они гарантированно получают не только самое последнее значение для этой переменной, но также и любые изменения, сделанные потоком в структуре данных до того, как он присвоил значение переменной.