Используйте летучий ключевое слово, чтобы намекнуть на компилятор, что значение может измениться в любой момент.
volatile int myInteger;
выше будет гарантировать, что любой доступ к переменной будет и из памяти без каких-либо конкретных оптимизации, и в результате все потоки, работающие на том же процессоре будет «видеть» изменения в переменной с той же семантикой как читает код.
Chris Jester-Young отметил, что в многопроцессорных системах может возникнуть проблема согласованности с таким изменением значения переменной.Это соображение, и это зависит от платформы.
На самом деле, есть действительно два соображения, которые следует учитывать относительно платформы. Это когерентность и атомарность транзакций памяти.
Атомность на самом деле является предметом рассмотрения как для одноплатных, так и для многопроцессорных платформ. Проблема возникает из-за того, что переменная, вероятно, является многобайтовой по своей природе, и возникает вопрос, может ли один поток увидеть частичное обновление значения или нет. т.е.: Некоторые байты изменены, контекстный переключатель, недопустимое значение, считанное прерыванием потока. Для одной переменной, которая находится на натуральном размерном слое машины или меньше и естественно выровнена, не должно вызывать беспокойства. В частности, тип int всегда должен быть в порядке, если он выровнен - это должно быть стандартным случаем для компилятора.
Относительно когерентности это потенциальная проблема в многопроцессорной системе. Вопрос в том, реализует ли система полную когерентность кэша или нет между процессорами. Если это реализовано, это обычно делается с протоколом MESI на аппаратном уровне. В вопросе не были указаны платформы, но как платформы Intel x86, так и платформы PowerPC являются кешами, согласованными между процессорами для нормально отображаемых областей данных программы. Поэтому этот тип проблемы не должен быть проблемой для обычных обращений к памяти данных между потоками, даже если есть несколько процессоров.
Последний вопрос относительно атомарности, который возникает, специфичен для атомарности чтения-модификации-записи. То есть, как вы гарантируете, что если значение будет считаться обновленным по значению и написанным, это произойдет атомарно, даже для процессоров, если их больше одного. Таким образом, для этого, чтобы работать без конкретных объектов синхронизации, потребовалось бы, чтобы все потенциальные потоки, обращающиеся к переменной, были читателями ТОЛЬКО, но ожидали, что только один поток может когда-либо быть писателем за один раз. Если это не так, тогда вам нужен объект синхронизации, доступный для обеспечения атомарных действий при действиях чтения-изменения-записи в переменную.
Это работает только в модели памяти Java 1.5 +. Стандарт C++ не предназначен для потоковой передачи, а волатильность не гарантирует согласованность памяти между процессорами. Для этого вам нужен барьер памяти. – 2008-09-22 23:29:57
Сам стандарт C++ в настоящее время не определяет эту семантику. Но все «последние» компиляторы почитают volatile как правильный намек. – Christopher 2008-09-22 23:38:21
Нет, они этого не делают. volatile гарантирует, что компилятор выполнит нагрузку, как указано, и поэтому учитывает потоки, но не гарантирует, что базовая подсистема памяти сохранит причинность в истинном многопроцессорной системе. – puetzk 2008-09-22 23:56:17