2014-02-17 3 views
4

У меня есть общий ресурс - простая POJO-упаковка HashMap, которая будет инициализирована один раз при запуске, а затем только когда-либо прочитанная, возможно одновременно, многими потоками (контекст - это веб-приложение). Нужно ли мне синхронизировать доступ к объекту (или, альтернативно, использовать одновременный хэшип) или безопасно иметь несколько одновременных чтений? Будет ли синхронизация значительными накладными расходами?Thread safety - чтение изменяемых объектов (java)

ответ

6

Вы можете пропустить синхронизацию для доступа на чтение к этой карте, если вы убедитесь, что все записи произошли до. Что это означает, описано в JLS 7 chapter 17.4.5.

На практике вам необходимо убедиться, что HashMap заселен до того, как будут запущены любые другие потоки, которые будут иметь к нему доступ, и после этого его содержимое не будет изменено.

Причина, по которой это решение будет работать, заключается в том, что вызов Thread.start() обеспечивает синхронизацию и поэтому гарантирует, что все изменения, сделанные до этого вызова, будут видны как старым, так и новым потокам после этого вызова. Если вы измените объект после этого вызова, эта гарантия будет потеряна и потребуется синхронизированный доступ.

+0

Это звучит проще, чем есть. В этом случае вы использовали бы тот факт, что вызов 'otherThread.start()' гарантирует, что любая модификация до этого вызова будет видима для 'otherThread'. Вы потеряете эту гарантию, если вы передадите ссылку на карту уже запущенному потоку некоторым несинхронизированным способом (AFAIK http://pastebin.com/p3mpbNxv должен иметь эту проблему.) Код, выполняющий его в правильном порядке, не гарантирует, что это фактически происходит в этом порядке, если вы не делаете что-то, что гарантирует такое происшествие-до отношения. – zapl

+0

@zapl Я указал на JLS и показал простое практическое решение. Я знаю, что происходит за кулисами, автор этого вопроса может либо узнать для себя из данной главы JLS, либо взять то, что я написал как нечто само собой разумеющееся. В любом случае, в этом случае он будет хорошим. – Dariusz

+0

Причина в том, что я чувствовал, что решающий момент в вашем втором абзаце трудно понять, если вы этого не знаете. Таким образом, он более или менее ориентировался на читателей/подсказывал вам, как вы могли бы ИМО улучшить ответ. – zapl

2

Если вы уверены, что вам нужно будет выполнять операции чтения, вам не нужна синхронизация. Это также та же причина, что существуют разные блокировки - чтение и запись в ReadWriteLock.

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

Поскольку у вас нет писателей, синхронизация не требуется.

1

Поскольку результаты нескольких чтений не зависят от последовательности событий, я бы сказал, что вы не сталкиваетесь с условиями гонки (http://en.wikipedia.org/wiki/Race_condition), и поэтому нет необходимости синхронизировать доступ.