Java избегать состояния гонки БЕЗ синхронизации / блокировки - PullRequest
7 голосов
/ 01 декабря 2011

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

Мой вопрос: есть ли другие (лучшие) способы избежать расы? Блокировка замедляет работу программы.

То, что я нашел:

  • с использованием атомарных классов, если существует только одна общая переменная.
  • использование неизменяемого контейнера для нескольких общих переменных и объявление этого объекта контейнера с помощью volatile. (Я нашел этот метод из книги «Параллелизм Java на практике»)

Я не уверен, что они работают быстрее, чем синхронизированные, есть ли другие лучшие методы?

спасибо

Ответы [ 5 ]

7 голосов
/ 01 декабря 2011

Избегайте состояния.Сделайте ваше приложение как можно безлимитным.Каждый поток (последовательность действий) должен вначале взять контекст и использовать этот контекст, передавая его из метода в метод в качестве параметров.

Когда эта техника не решает все ваши проблемы, используйте механизм, управляемый событиями.Когда ваш код должен поделиться чем-то с другими компонентами, он отправляет событие (сообщение) на какую-то шину (тему, очередь, что угодно).Компоненты могут регистрировать слушателей, чтобы прослушивать события и реагировать соответствующим образом.В этом случае нет условий гонки (кроме вставки событий в очередь).Если вы используете готовую очередь и не кодируете ее самостоятельно, она должна быть достаточно эффективной.

Также обратите внимание на модель актеров.

4 голосов
/ 01 декабря 2011

Атомика действительно более эффективна, чем классические блокировки, благодаря своему неблокирующему поведению, то есть поток, ожидающий доступа к ячейке памяти, не будет переключаться по контексту, что экономит много времени.

Вероятно, лучшее руководствокогда требуется синхронизация, стоит посмотреть, как можно максимально уменьшить размер критического сечения.Общие идеи включают в себя:

  1. Использование блокировок чтения-записи вместо полных блокировок, когда требуется запись только части потоков.
  2. Поиск способов реструктуризации кода для уменьшения размеракритических секций.
  3. Используйте атомарные элементы при обновлении одной переменной.
  4. Обратите внимание, что некоторые алгоритмы и структуры данных, которые традиционно нуждаются в блокировках, имеют версии без блокировок (однако они более сложные).
3 голосов
/ 01 декабря 2011

Ну, во-первых, классы Atomic используют блокировку (через синхронизированные и изменчивые ключевые слова) так же, как если бы вы делали это вручную.

Во-вторых, неизменяемость отлично работает для многопоточности, вам больше не нужны блокировки монитора и тому подобное, но это потому, что вы можете только читать свои неизменяемые объекты, вы можете изменять их.Избавьтесь от синхронизированного / изменчивого, если вы хотите избежать состояния гонки в многопоточной Java-программе (то есть, если несколько потоков будут считывать и записывать одни и те же данные).Лучше всего, если вам нужна более высокая производительность, избегать хотя бы некоторых встроенных потоковобезопасных классов, которые делают своего рода более общую блокировку, и создавать собственную реализацию, которая более привязана к вашему контексту и, таким образом, может позволить вамиспользуйте более гранулярную синхронизацию и захват блокировки.

Проверьте эту реализацию BlockingCache, выполненную ребятами из Ehcache;

http://www.massapi.com/source/ehcache-2.4.3/src/net/sf/ehcache/constructs/blocking/BlockingCache.java.html

2 голосов
/ 01 декабря 2011

Одна из альтернатив - сделать общие объекты неизменяемыми .Проверьте этот пост для более подробной информации.

1 голос
/ 01 декабря 2011

Вы можете выполнить до 50 миллионов блокировок / разблокировок в секунду.Если вы хотите, чтобы это было более эффективно, я предлагаю использовать больше блокировки зерна курса.т.е. не блокируйте каждую мелочь, но есть блокировки для более крупных объектов.Если у вас гораздо больше блокировок, чем у потоков, у вас меньше шансов на конфликты, а наличие большего количества блокировок может просто добавить издержки.

...