Ява изменчивые ключевые слова
В обработке параллелизма Java существует большая путаница в использовании летучих ключевых слов. Я думаю, что использование этого ключевого слова может сделать все хорошо при использовании многопоточной обработки параллелизма.
Язык Java поддерживает многопоточное. Чтобы решить проблему параллелизма потока, внутри языка вводятся синхронные блоки и летучие ключевые слова.
синхронизированный
Все знакомы с синхронизированными блоками, и они реализованы с помощью синхронизированного ключевого слова. С помощью синхронизированных и блочных операторов только один поток может использовать их одновременно при доступе к мультипотчикам.
Синхронизированный модифицированный метод или кодовый блок.
нестабильный
Для переменных, измененных с помощью летучих, поток будет считывать наиболее модифицированное значение переменной каждый раз, когда он использует переменную. Волвалование легко неправильно используется и используется для атомных операций.
Давайте посмотрим пример ниже. Мы реализуем счетчик. Каждый раз, когда запускается поток, метод Counter Inc будет вызоваться, чтобы добавить один в счетчик.
Среда выполнения - JDK версия: JDK1.6.0_31, память: 3G ЦП: x86 2.4G
счетчик открытого класса {public static int count = 0; public static void inc () {// задержка здесь составляет 1 миллисекунду, что делает результат очевидным try {thread.sleep (1); } catch (прерывание Exception e) {} count ++; } public static void main (string [] args) {// запустить 1000 потоков одновременно для выполнения вычислений i ++ и см. Фактический результат для (int i = 0; i <1000; i ++) {new runnable (new Runnable () {@Override public void run () {count.inc ();}}). start (); } // Значение каждого запуска здесь может быть различным, может быть, 1000 System.out.println («Запустить результат: counter.count =" + counter.count); }}运行结果:Counter.count= 995
实际运算结果每次可能都不一样,本机的结果为:运行结果:Counter.count= 995 ,可以看出,在多线程的环境下,Counter.count并没有期望结果是1000
Многие люди думают, что это проблема параллелизма. Вам нужно только добавить volatile很多人以为,这个是多线程并发问题,只需要在变量count之前加上就可以避免这个问题,那我们在修改代码看看,看看结果是不是符合我们的期望
Общественный счетчик класса {public volatile Static int count = 0; public static void inc () {// задержка здесь составляет 1 миллисекунду, что делает результат очевидным try {thread.sleep (1); } catch (прерывание Exception e) {} count ++; } public static void main (string [] args) {// запустить 1000 потоков одновременно, выполните расчеты i ++ и см. Фактический результат для (int i = 0; i <1000; i ++) {new Thread (new Runnable () {@Override public void run () {contre.inc ();}). start (); } // Значение каждого запуска здесь может быть различным, возможно, 1000 System.out.println ("Запустить результат: counter.count =" + counter.count); }}Результат работы: counter.count = 992
Результат работы по -прежнему не составляет 1000, как мы ожидали. Давайте проанализируем приведенные ниже причины
В статье сбора мусора Java описывается распределение памяти в момент JVM. Одной из областей памяти является стек виртуальных машин JVM, и в каждом потоке есть стек потоков при запуске.
Стек потоков сохраняет информацию о значении переменной во время выполнения потока. Когда поток обращается к значению определенного объекта, сначала найдите значение переменной, соответствующей памяти кучи через ссылку объекта, а затем поместите память кучи
Конкретное значение переменной загружается в локальную память потока, и создается копия переменной. После этого поток больше не имеет никаких отношений со значением переменной объекта в памяти кучи, но непосредственно изменяет значение переменной копии.
В определенный момент после модификации (до выхода поток) значение копии переменной потока автоматически записывается обратно в переменную объекта в куче. Таким образом, значение объекта в куче изменится. Следующая картина
Опишите это письменное взаимодействие
Читать и загружать переменные копии из основной памяти в текущую рабочую память
Используйте и назначьте код выполнения для изменения значения общей переменной
Хранить и написать обновление основного контента, связанного с памятью с данными рабочей памяти
где использование и назначение может появиться несколько раз
Тем не менее, эти операции не являются атомными, то есть после нагрузки чтения, если основная переменная числа памяти изменена, значение в рабочей памяти потока не вызовет соответствующие изменения, поскольку она была загружена, поэтому рассчитываемый результат будет отличаться от ожидаемого.
Для переменных, модифицированных летучими, виртуальная машина JVM гарантирует, что значение, загруженное из основной памяти в потоку рабочей памяти, является последним
Например, если поток 1 и поток 2 выполняют операции чтения и загрузки, и обнаружите, что значение счета в основной памяти составляет 5, то последнее значение будет загружено
После того, как количество кучи изменяется в потоке 1, он будет записан в основную память, а переменная счета в основной памяти станет 6.
Поскольку поток 2 уже выполнил операцию чтения и нагрузки, значение переменной основного количества памяти также будет обновлено до 6 после операции.
Это приводит к тому, что параллелизм возникает после того, как два потока изменяются с помощью летучивого ключевого слова во времени.
Спасибо за чтение, я надеюсь, что это поможет вам. Спасибо за поддержку этого сайта!