Код, защищенный версиями, без использования ключевого слова `synchronized`?

Каковы возможные способы обеспечения безопасности кода без использования ключевого слова synchronized?

Ответ 1

Собственно, много способов:

  • Не требуется синхронизация вообще, если у вас нет изменяемого состояния.
  • Нет необходимости в синхронизации, если изменяемое состояние ограничено одним потоком. Это можно сделать, используя локальные переменные или java.lang.ThreadLocal.
  • Вы также можете использовать встроенные синхронизаторы. java.util.concurrent.locks.ReentrantLock имеет те же функции, что и блокировка, доступ к которой вы используете при использовании блоков и методов synchronized, и она еще более эффективна.

Ответ 2

Только переменные/ссылки локальны для методов. Или убедитесь, что любые переменные экземпляра неизменяемы.

Ответ 3

Вы можете сделать свой код потокобезопасным, сделав все данные неизменяемыми, если нет изменчивости, все поточно-безопасно.

Во-вторых, вы можете захотеть взглянуть на java-параллельный API, в котором предусмотрено обеспечение блокировок чтения/записи, которые работают лучше, если есть много читателей и несколько авторов. Чистое синхронизированное ключевое слово также заблокирует двух читателей.

Ответ 4

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

Самая большая защита использует ключевое слово synchronized. Кроме того, существует как минимум два уровня возможностей, каждый из которых имеет свои преимущества.

Замки/семафоры

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

Замки могут быть намного эффективнее, если вы выберете блокировку для соответствия алгоритму.

Atomics

Использование AtomicReference, например, часто может обеспечить полностью свободную от блокировки функциональность. Это может обеспечить огромные преимущества.

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

Например, если вы хотите изменить значение, которое вы можете прочитать, а затем записать новое значение, пока оно остается старым. Это называется "сравнить и установить" или cas и обычно может быть реализовано на аппаратном обеспечении, и поэтому является чрезвычайно эффективным. Все, что вам тогда нужно, это что-то вроде:

long old = atomic.get();
while ( !atomic.cas(old, old+1) ) {
  // The value changed between my get and the cas. Get it again.
  old = atomic.get();
}

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

Ответ 5

Зачем вам это нужно?

Использование только локальных переменных/ссылок не решит большинство сложных бизнес-потребностей. Кроме того, если переменная экземпляра неизменяема, их ссылки могут быть изменены другими потоками.

Один из вариантов - это что-то вроде SingleThreadModel, но он сильно обескуражен и устарел.

u также может смотреть на одновременный api, как было предложено выше, Kal