Подтвердить что ты не робот

Почему переменные в Java нестабильны по умолчанию?

Возможно, подобный вопрос:

Вы когда-нибудь использовали ключевое слово volatile в Java?


Сегодня я отлаживал свою игру; У него была очень сложная проблема с резьбой, которая появлялась каждые несколько минут, но ее было трудно воспроизвести. Поэтому сначала я добавил ключевое слово synchronized для каждого из моих методов. Это не сработало. Затем я добавил ключевое слово volatile для каждого поля. Проблема, похоже, просто исправилась.

После некоторого эксперимента я обнаружил, что ответственным за поле был объект GameState, который отслеживал текущее состояние моей игры, которое может быть либо играющим, либо занятым. Когда занят, игра игнорирует вход пользователя. У меня был поток, который постоянно менял переменную state, в то время как поток Event читает переменную state. Однако после того, как один поток изменит переменную, потребуется другой секунде, чтобы другой поток распознал изменения, что в конечном итоге вызывает проблему.

Это было исправлено, сделав переменную состояния volatile.

Почему переменные в Java volatile по умолчанию и почему не использовать ключевое слово volatile?

4b9b3361

Ответ 1

Короче говоря, изменчивые переменные - будь то на Java или С# - никогда не кэшируются локально внутри потока. Это не имеет большого значения, если вы не имеете дело с многопроцессорным/многоядерным процессором с потоками, выполняемыми на разных ядрах, поскольку они будут искать один и тот же кеш. Когда вы объявляете переменную как изменчивую, все чтения и записи поступают прямо и прямо в фактическое место основной памяти; нет кеша. Это имеет значение, когда дело доходит до оптимизации, и делать это без необходимости (когда большинство переменных не обязательно должно быть изменчивым) будет налагать штраф за производительность (ничтожный, как это может быть или не быть) при относительно небольшом коэффициенте усиления.

Ответ 2

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

Более приятной альтернативой является использование других строительных блоков в java.util.concurrent, некоторые из которых являются блокируемыми, но не путайте с головой так же, как пытаетесь сделать все сами на низком уровне.

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

Ответ 3

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

Ответ 4

В то время как другие верны, указывая, почему было бы плохой идеей дефолта по умолчанию, есть еще один момент: очень вероятно, что в вашем коде есть ошибка. Переменные редко необходимо сделать изменчивыми: всегда есть способ правильно синхронизировать доступ к переменным (либо с помощью синхронизируемого ключевого слова, либо с использованием объектов AtomicXxx из java.util.concurrency): исключения будут включать в себя код JNI, манипулирующий ими (который не связан синхронизацией директивы).

Поэтому вместо добавления изменчивости вы можете выяснить, ПОЧЕМУ он разрешил проблему. Это не единственный способ решить эту проблему, и, вероятно, лучший способ.

Ответ 5

Поскольку компилятор не может оптимизировать изменчивые переменные.

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

Ответ 6

Объявление переменных волатильных обычно оказывает огромное влияние на производительность. В традиционных однопоточных системах было легко знать, что должно быть изменчивым; это были те вещи, которые обращались к аппаратным средствам.

В многопоточном режиме это может быть немного сложнее, но я бы рекомендовал использовать уведомления и очереди событий для обработки передаваемых данных между аддами в leau магических переменных. В Java это может не иметь большого значения; в C/С++ вы столкнулись бы с проблемой, когда эти переменные не могут быть заданы атомарно базовым оборудованием.