2016-09-27 7 views
3

Если у меня есть что-то вроде этого snippet-Синхронизация синхронизированного списка

public List<E> list = Collections.synchronizedList(new ArrayList<E>()); 

тогда, если я делаю какие-то операции внутри методы -

boolean absent = !list.contains(x);    // Statement 1 
if(absent)          // Statement 2 
    list.add(x);        // Statement 3 

мне нужно сделать, чтобы обернуть выше заявление в synchronized(list){ ... } к совершать операции atomic?

+1

Я не думаю, что этот вопрос кратен одному из приведенных в ссылке. Этот запрос предусматривает синхронизацию блоков кода в списке, а другой - синхронизацию вызовов одного метода. Даже их ответы различны (необходимо для этого, а не для другого). – uoyilmaz

+1

@uoyilmaz Это каноническое покрытие, использующее 'synchronized' с методом' synchronizedList'. И [ответы] (http://stackoverflow.com/a/9468329/1743880) также охватывают эту точку: * Если блок выполняет несколько операций в списке [...], тогда синхронизированный не лишний * – Tunaki

ответ

3

Нужно ли обертывать вышеуказанные утверждения внутри synchronized(list){ ... }, чтобы сделать операции атомарными?

Да иначе ваш List может быть изменен в другом месте в коде в окне времени вы называете contains и add, которые могут вызвать состояния гонки выдает.

Это делает меня, что то, что использование Collections.synchronizedList?

Collections.synchronizedList делает ваш List поточно таким образом, что вы можете изменить его одновременно, но по-прежнему все вызовы методов выполняются атомарно. В приведенном выше случае вы вызываете contains и add, что вам нужно выполнить атомарно, потому что в противном случае, если в другом месте мы вызываем add, результат contains может быть устаревшим, что привело бы к проблеме состояния гонки. Единственный способ предотвратить проблемы с условиями гонки - использовать блок синхронизации на том же объектном мониторе, который в вашем случае равен list.

+0

Это заставляет меня подумайте, что такое использование Collections.synchronizedList? –

+0

@ShirgillFarhanAnsari Предположим, что два потока, вызывающих remove(), параллельны. Если ваш основной список не синхронизирован, будут происходить смешные вещи. Дело в том, чтобы предотвратить проблемы, когда ** независимые ** изменения в синхронизированном списке происходят параллельно. Вы говорите о наборе вызовов, которые «принадлежат друг другу»! – GhostCat

+1

Спасибо за помощь. Мне довелось увидеть ваш профиль. Вы, как и я, подумали, что это JEE. Это никогда не было JEE. Его JavaEE, поскольку я был исправлен специалистом по веб-приложениям BalusC (член группы экспертов JSF 2.3). –

1

Исправить. Теоретически все может случиться между вашими утверждениями 1 и 3; таким образом: если вы хотите, чтобы они произошли «атомарно»; то вам нужно каким-то образом превратить их в «одну транзакцию».

Использование synchronized(list) - разумный способ добраться туда.

2

Да, синхронизированный список делает вызов метода атомарным, но вам нужно синхронизировать доступ, если вы хотите сделать несколько операторов атомарными (например, при итерации по списку и т. Д.).

Смежные вопросы