Летучие не поможет вам на всех. Значение volatile
состоит в том, что изменения, внесенные потоком A в общую переменную, сразу видны в потоке B. Обычно такие изменения могут быть в каком-то кеше, видимом только для потока, который их создал, а volatile
просто сообщает JVM не делать кеширования или оптимизации, что приведет к задержке изменения значения.
Так что это не средство синхронизации. Это всего лишь средство обеспечения видимости изменений. Более того, это изменение переменной , а не на объект , на который ссылается эта переменная. То есть, если вы отметите list
как volatile
, это будет иметь значение только в том случае, если вы назначьте новый список list
, а не если вы измените содержание списка!
Ваше другое предложение было сделать ArrayList
синхронизированной переменной. Здесь есть заблуждение. Переменные не могут быть синхронизированы. Единственное, что можно синхронизировать, это код - либо целый метод, либо конкретный блок внутри него. Вы используете объект в качестве монитора синхронизации .
Монитор - это сам объект (фактически, это логическая часть объекта, который является монитором), а не переменная. Если вы назначили другой объект той же переменной после синхронизации по старому значению, то у вас не будет доступ к вашему старому монитору.
Но в любом случае это не тот объект, который синхронизирован, это код, который вы решили синхронизировать с использованием этого объекта.
В качестве монитора вы можете использовать list
для синхронизации операций с ним. Но вы не можете синхронизировать list
.
Предположим, что вы хотите синхронизировать операции, используя список в качестве монитора, вы должны разработать его так, чтобы поток записи не удерживать блокировку все время. То есть, он просто захватывает его для одного чтения-обновления, вставки и т. Д., А затем освобождает его. Захватывает его снова для следующей операции, а затем освобождает. Если вы синхронизируете весь метод или весь цикл обновления, другой поток никогда не сможет его прочитать.
В читальном потоке, вероятно, вы должны сделать что-то вроде:
List<T> listCopy;
synchronized (list) {
listCopy = new ArrayList(list);
}
// Use listCopy for displaying the value rather than list
Это происходит потому, что отображение является потенциально медленно - она может включать I/O, обновление GUI и т.д. Таким образом, чтобы свести к минимуму время блокировки, вы просто скопируйте значения из списка, а затем отпустите монитор, чтобы поток обновления мог выполнять свою работу.
Кроме того, есть много типов объектов в java.util.concurrent
упаковке и т.д., которые разработаны, чтобы помочь в подобных ситуациях, когда одна сторона пишет, а другой для чтения. Проверьте документацию - возможно, ConcurrentLinkedDeque
будет работать для вас.
Вместо 'ArrayList' вы можете использовать одну из очередей из пакета' concurrency'. – Titus
Вы не можете сделать ArrayList 'volatile'. Вы не можете сделать объект изменчивым. Единственными вещами на Java, которые могут быть неустойчивыми, являются _fields_. –