Как выполняется переключение потоков?
Как я понимаю, в контексте процесса переключение резервных копий ОС "регистры" и указатель инструкции (также часть регистра).
Но в случае переключения между потоками внутри процесса ОС будет делать резервную копию полной памяти регистров и стека?
Причина, по которой я спрашиваю, заключается в том, чтобы понять, имеет ли ключевое слово volatile Java какое-либо значение в случае одноядерных процессоров.
Ответы
Ответ 1
если ключевое слово volatile Java имеет какое-либо значение в случае одноядерных процессоров.
Оптимизация, используемая jit-компилятором, может вызвать неожиданное поведение.
static boolean foo = true;
public void bar(){
while(foo){
//doSomething
//do not modify foo in here
}
}
это может быть оптимизировано, так как foo не изменяется в цикле.
public void bar(){
while(true){
//Now this loop never ends
//changes to foo are ignored
}
}
make foo
volatile
сообщит компилятору jit, что foo
может быть изменен другим потоком, и доступ к нему не должен быть оптимизирован.
Это допустимое поведение, поскольку доступ к сквозным потокам гарантирован только с
- летучие и синхронизированные ключевые слова
- классы, которые должны быть потокобезопасными (например, java.util.concurrent. *)
Обновление
Ключевое слово volatile не влияет на переключение контекста, однако оно влияет на оптимизацию чтения и записи переменных. Это не только влияет на использование кеша процессора (важно для многоядерных систем), но и оптимизаций, используемых компилятором только во времени, как показано выше (важно для всех систем).
Ответ 2
Переключение потоков действительно означает сохранение всех регистров вычислений и всего стека, просто потому, что каждый поток действительно имеет отдельный стек памяти.
Ключевое слово volatile
по-прежнему важно для многопоточности, даже в одноядерных средах, из-за того, как работает модель памяти Java. volatile
переменные не хранятся в кэше или регистре любого типа, а всегда извлекаются из основной памяти, чтобы гарантировать, что каждый поток всегда видит самое последнее значение переменной.
Ответ 3
понять, что ключевое слово volatile Java имеет какое-либо значение в случае одноядерных процессоров.
Эта линия мышления неразумна. Вы должны программировать в соответствии с (документированным) определением API и виртуальной машины. Вы не должны полагаться на что-то (в данном случае на эффект volatile
), имеющее особый эффект или недостаток эффекта, который не является частью его документированного определения. Даже если эксперимент предполагает, что он имеет особое поведение в определенных обстоятельствах. Потому что он будет укусить вас.
Ответ 4
Проверьте JSR 133 и, в частности, раздел "Что делает volatile?"
Неустойчивые поля - это специальные поля которые используются для передачи состояния между потоками. Каждое чтение volatile будет видеть последнюю запись в что волатильно нитью; в эффект, они обозначаются программист как поля, для которых он никогда не приемлемо видеть "устаревшие" значение в результате кэширования или переназначения.
Это полезное введение и описание того, как volatile
работает с моделью памяти JVM.
Ответ 5
Да, даже для одноядерных процессоров, volatile
по-прежнему полезен. Он сообщает компилятору, что значение нужно перечитывать из памяти каждый раз, когда он читает (поскольку другой поток может его обновлять), а не просто кэшироваться в регистре.
Ответ 6
Я знаю, что делает volatile
, но я пытаюсь понять, почему это необходимо. Позвольте мне уточнить.
Как упоминалось выше josefx. Если у нас есть что-то вроде: -
while(run) {
//do something but don't modify run
}
Если какой-то другой поток превратит run
в false
, тогда цикл while никогда не закончится. Как уже упоминалось ранее Yuval A, во время переключения контекста потока также сохраняются регистры. Поэтому я думаю, что это работает так.
Если какой-либо поток изменяет значение run
, значение будет изменено только в регистре. Во время переключения контекста потока Java не будет синхронизировать это значение регистра с копией в ОЗУ, если явно не указано как volatile
. Таким образом, каждый поток будет работать со своей версией run
. Но это понятие не относится к непримитивам и примитивам, таким как integer и т.д., Которые не будут вписываться полностью в регистр, заставляя их синхронизироваться с копией RAM.