Java произошла до начала потока - PullRequest
3 голосов
/ 04 октября 2011

Я где-то читал, что запуск потока имеет какой-то особый эффект на случайность до отношения. Теперь я не уверен, гарантирует ли мой код случайность до отношений, поэтому, пожалуйста, просветите меня.

У меня есть поток Dispatcher и класс Worker, реализующий интерфейс Runnable. Поток Dispatcher создает новый экземпляр Worker и заполняет LinkedList в экземпляре Worker с помощью метода add элементами.

Затем Диспетчер передает экземпляр Worker в ExecutorService с помощью метода execute.

Затем метод run в классе Worker начинает получать доступ и удалять вещи из LinkedList.

Видит ли недавно запущенный экземпляр Worker то же состояние LinkedList, в котором его оставил Диспетчер? Или может быть, что LinkedList находится в каком-то нерешительном состоянии? Должен ли я заполнить LinkedList в синхронизированном методе?

Ответы [ 3 ]

4 голосов
/ 04 октября 2011

Согласно документации: ExecuterService Javadocs

Эффекты согласованности памяти: действия в потоке перед отправкой задачи Runnable или Callable в ExecutorService происходят до того, как какие-либо действия, предпринятые этой задачей, которые, в свою очередь, происходят до получения результата через Future.get () ,

Это означает, что ваша концепция верна.

2 голосов
/ 04 октября 2011

Спецификация языка Java пишет :

Действие, которое запускает поток синхронизируется с первым действием в потоке, которое он запускает.

Если действие x синхронизируется с следующим действием y, то у нас также есть hb(x, y).

Если у нас есть два действия x и y, мы пишем hb(x, y), чтобы указать, что x происходит до y.

Однако из вашего описания не ясно, относится ли это кваш случай, когда вы говорите об исполнителе, но не объясняете, когда этот исполнитель создан или его рабочие потоки запущены.

Что имеет значение, так это следующий отрывок из JavaDoc исполнителя :1031 *

Эффекты согласованности памяти: Действия в потоке перед отправкой Runnable объекта в Executor , произошедшего до его выполнения, возможно, в другом потоке.

Следовательно, ваш код в безопасности, пока поток диспетчера нетболее длительный доступ к списку после отправки Runnable.

1 голос
/ 04 октября 2011

Если используются блокирующие или другие синхронизирующие примитивы, и вы просто используете простой старый ArrayList, тогда два потока могут видеть разные состояния.

При координации работы между двумя отдельными потоками необходимолибо используйте потокобезопасную / параллельную структуру данных, либо используйте код синхронизации, чтобы гарантировать согласованный «снимок памяти» между потоками.

Одна из причин, по которой это важно, связана с кэшированием.Два потока, выполняющиеся одновременно на разных процессорах, могли кэшировать некоторые объекты в разных локальных регистрах (которые являются локальными для этих процессоров).

...