В многопоточности мы обычно путаем
Volatile, Synchronized и Atomic.

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

  1. проблема видимости
  2. проблема синхронизации

1. проблема видимости

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

у нас есть глобальная переменная status = true, а thread-1 начинает некоторую обработку, когда status = true

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

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

Чтобы решить вышеуказанную проблему, нам нужно использовать ключевое слово volatile

public volatile boolean status = true ;

если вы укажете volatile для конкретной переменной, все изменения, которые вы сделаете в каждом потоке, будут записаны в общий кеш.

2. проблема с синхронизацией

В этом сценарии это похоже на одну операцию, а не на одну операцию.

читать → изменять → писать

у нас есть значение int = 1 . когда поток-1 запускается, сначала запускается i=2, а затем запускается поток-2, затем i = 3 .

И наоборот, если поток-2 запускается первым, то также i=2 и позже поток-1, затем i=3.

Но в высокопараллельных средах иногда это работает неправильно.

если JVM планирует поток, который зависит друг от друга

  1. поток 1 → прочитать значение = 1 → передан в общий кеш, потому что значение изменчиво.
  2. поток 2 → прочитать значение = 1 → передан в общий кеш, потому что значение изменчиво
  3. поток 1 → обновить значение = 2 → передан в общий кеш, поскольку значение изменчиво, но поток 2 не читает из общего кеша, поскольку операция чтения уже завершена
  4. снова поток 2 → обновить значение = 2 зафиксированный общий кеш, что совершенно неверно.

Это проблема синхронизации ……..

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

Используйте Case, чтобы понять проблему синхронизации:

  1. В приведенной выше программе я использовал ConcurrentHashMap, состоящую из названия партии в качестве ключа и количества голосов в качестве значения.
  2. Я взял 5 тредов и Каждый тред проголосовал 1000 голосов за каждую партию , т. е. в соответствии с нашими ожиданиями, после запуск всех тем каждая партия должна и должна содержать 5000 голосов
  3. Но я запускаю эти 5 потоков в многопоточной среде, из-за этогоя получаю другой вывод, как показано как показано ниже

нам нужно использовать атомарные переменные для решения вышеуказанной проблемы
решение:

Разница между volatile и atomic

  1. volatile подходит только для случаев чтение →запись
  2. атомарные переменные используются для случаев чтение →обновление →запись

3. Используйте Case, чтобы избежать проблем с видимостью и синхронизацией с реализацией singleton.

  1. В среде с высокой параллельной нагрузкой существует вероятность того, что войдут два потока.

2. JIT-компилятор переупорядочивает байтовый код таким образом, что ссылка на getInstance() устанавливается до того, как конструктор завершит свое выполнение. Это означает, что существует вероятность того, что метод getInstance() возвращает объект, который не полностью инициализирован.

Ява 5 . например переменные, переменные, помеченные как volatile, видны другим потокам только тогда, когда конструктор объекта полностью инициализирован

Вывод ……

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

  1. изменчивый → флаги
  2. Атомарные переменные → счетчики
  3. Атомарные ссылки → Кэш
  4. блок синхронизации с volatile →variable является глобальным и требует видимости для каждого потока, каково текущее состояние объекта.