Многие друзья, возможно, слышали о том, что ключевое слово летучие и, возможно, использовали его. До Java 5 это было противоречивое ключевое слово, так как использование его в программах часто приводило к неожиданным результатам. Только после Java 5 летучие ключевые слова восстановили свою жизненную силу. Хотя нестабильное ключевое слово буквально просто для понимания, его нелегко использовать его хорошо.
1. Предисловие
JMM обеспечивает летучие определения переменной, окончательные, синхронизированные блоки для обеспечения видимости.
Для переменных, измененных с помощью летучих, поток будет считывать наиболее модифицированное значение переменной каждый раз, когда он использует переменную. Волвалование легко неправильно используется и используется для атомных операций. Я написал несколько тестовых примеров, вы можете попробовать.
2. Основная программа
Открытый класс Main {public static void main (string [] args) бросает прерывание {list <thread> threadlist = new ArrayList <thread> (); for (int i = 0; i <10; ++ i) {thread = new Thread (new Runnable () {@OverridePublic run () {Single.holder.instance.add ();}}); threadlist.add (thread); thread.start ();} для (потока потока: threadlist) thread.join (); System.out.println (single.holder.instance.x);}}3. Тест на режим синглтона
1. Нет летучих, без синхронизации
Класс Single {public int x = 0; public void add () {try {timeUnit.milliseconds.sleep (50);} catch (прерывание e) {e.printstacktrace ();} ++ this.x;} public Static Class Holder {public static = new Single ();}}}}}}}}}}}}}}Выходные результаты: 8, 9 и 10 появились все. Вы можете работать больше и попробовать больше, и вы найдете разные результаты.
2. Существует летучие, но нет синхронизированного
Класс Single {public volatile int x = 0; public void add () {try {timeUnit.milliseconds.sleep (50);} catch (urruptedExcept e) {e.printstacktrace ();} ++ this.x;} public Static Class Holder {public Static Single = Single ();}}}}}}}}}}}}Результат вывода: максимальное количество случаев составляет 9 и 10.
3. Нет летучих, синхронизированных
Класс Single {public int x = 0; public synchronized void add () {try {timeUnit.milliseconds.sleep (50);} catch (urruptEdexcept e) {e.printstacktrace ();} ++ this.x;} public Static Class Holder {public Static single = new Single ();}}}}}}}}}}}}}}}}}}}}Результат вывода: независимо от того, сколько раз вы запустите, это будет 10.
4. О применении летучих в DCL (двойная проверка блокировки)
открытый класс lazysingleton {private int somefield; частный статический экземпляр Lazysingleton; private lazysingleton () {this.somefield = new Random (). Nextint (200) +1; // (1)} public static lazysingleton getInstance () {if (exance == null) {// (2) synchronized (lazysingleton.class) {// (3) if (ancess == null) {// (4) encement = new lazysingleton (); // (5)}}} return Encement; // (6)} public int getSomefield () {return this.somefield; // (7)}}Прежде всего, позвольте мне объяснить, почему этот метод письма не работает на Java!
Предположим, что поток I впервые вызывает метод getInstance (), а затем поток II также вызывает метод getInstance () и метод GetSomefield (). Что мы хотим объяснить, так это то, что утверждение потока I (1) не произошло, потому что прежнее утверждение потока II (7). Когда Thread II выполняет оператор (2) метода getInstance (), поскольку доступ к экземпляру не находится в синхронном блоке, темт II может наблюдать или не наблюдать за написанием потока I к экземпляру в операторе (5), то есть значение экземпляра может быть пустым или непустым. Сначала мы предполагаем, что значение экземпляра не является пустым, поэтому мы наблюдаем, что нить я пишет экземпляр. В настоящее время Thread II выполнит оператор (6) и непосредственно вернет значение этого экземпляра, а затем вызовет метод GetSomefield () в этом экземпляре. Этот метод также вызывается без какой -либо синхронизации. Следовательно, вся операция потока II называется без синхронизации. Это показывает, что нет никаких отношений между утверждением (1) потока I и утверждением (7) потока II. Это означает, что теме II может не иметь возможности наблюдать за значением, записанным потоком I, до некоторого на сфере в операторе (1). Это проблема с DCL. Это смешно, верно? DCL изначально был предназначен для того, чтобы избежать синхронизации, и он достиг этой цели. Именно из -за этого это в конечном итоге было наказано. В таких программах есть серьезные ошибки, хотя вероятность обнаружения такой ошибки определенно намного ниже, чем вероятность победы в лотерею, и она мимолетна. Что еще более ужасно, так это то, что даже если это произойдет, вы не подумаете, что это было вызвано DCL.
Насколько я понимаю, что и теме I, и Thread II имеют собственное рабочее хранилище. После потока I создает экземпляр, время обновления памяти неясно, поэтому вполне возможно, что поток II не может наблюдать за значением, написанным потоком I, для некоторого сформированного при операторе (1).
Итак, поскольку в Java 5 добавлено дополнительное правило.
• Операция записи в нестабильное поле происходит до последующих операций чтения в том же поле.
Используя это правило, мы можем объявить экземпляр изменчивым, то есть частный летучий статический экземпляр Lazysingleton;
Согласно этому правилу, мы можем получить утверждение потока I (5) -> предложение потока II (2) (то есть, нить), в соответствии с правилом с одной отделкой, утверждение потока I (1) -> предложение потобого I (5) и предложения поток II (2) -> предложение нити II (7), и, согласно правилам доставки, что может быть поток I (1) -> Поставка. Значение потока I до некоторого сформулированного в утверждении (1), и программа может получить правильное поведение.
Дополнение: До Java5 нет разницы между синхронной семантикой окончательного поля и другими переменными. В Java5, как только конечная переменная установлена в конструкторе (при условии, что эта ссылка не протекает в конструкторе), другие потоки определенно увидят значения, установленные в конструкторе. Проблема с DCL заключается в том, что мы видим значение по умолчанию переменной элемента объекта, чтобы мы могли установить переменную некоторую поле Lazysingleton в финал, чтобы она могла правильно работать в Java5.
Вышеуказанный контент - это знание нестабильных ключевых слов в Java, представленных вам редактором. Я надеюсь, что это будет полезно для всех!