Volatile 1 страница
Если объявление_поля включает модификатор volatile, поля, введенные этим объявлением, являются полями c модификатором volatile. Способы оптимизации, переупорядочивающие инструкции, для полей не-volatile могут привести к непредвиденным и непредсказуемым результатам в многопоточных программах, которые обращаются к полям без синхронизации, такой как предоставляемая оператором_блокировки; (§8.12). Эти оптимизации могут выполняться компилятором, системой поддержки выполнения или оборудованием. Для полей volatile такие переупорядочивающие оптимизации ограничены. · чтение поля volatile называется чтением volatile. У чтения volatile имеется «семантика захвата», то есть, оно гарантированно выполняется прежде любых обращений к памяти, расположенных после него в последовательности инструкций; · запись поля volatile называется записью volatile. У записи volatile имеется «семантика освобождения», то есть, оно гарантированно выполняется после всех обращений к памяти, расположенных до инструкции записи в последовательности инструкций. Эти ограничения приводят к тому, что все потоки будут видеть записи volatile, выполняемые любым другим потоком, в том порядке, в каком они выполнялись. Не требуется соответствующая реализация для обеспечения единого общего упорядочения записей volatile, представляемого для всех потоков выполнения. Поле volatile должно имеет один из следующих типов: · ссылочный_тип;; · тип byte, sbyte, short, ushort, int, uint, char, float, bool, System.IntPtr или System.UintPtr; · перечисляемый_тип, имеющий базовый тип перечисления byte, sbyte, short, ushort, int или uint. Пример. using System; class Test static void Thread2() { static void Main() { // Run Thread2() in a new thread // Wait for Thread2 to signal that it has a result by setting Для этого примера выходом является: result = 143 В этом примере метод Main запускает новый поток, выполняющий метод Thread2. Этот метод сохраняет значение в поле не-volatile с именем result, затем сохраняет true в поле volatile с именем finished. Главный поток ожидает, пока поле finished не будет установлено в true, затем считывает поле result. Так как finished объявлено как volatile, главный поток должен сосчитать значение 143 из поля result. Если бы поле finished не было объявлено как volatile, то сохранение в result могло быть видимым в главном потоке после сохранения в finished, и главный поток мог прочитать значение 0 из поля result. Объявление finished как поля volatile предотвращает такую несогласованность. 10.5.4 Инициализация поля; Начальным значением поля, как статического, так и поля экземпляра, является значение по умолчанию (§5.2) типа поля. Невозможно видеть значение поля до выполнения этой инициализации по умолчанию, и поэтому поле никогда не бывает «неинициализированным». Пример. using System; class Test static void Main() { В этом примере производятся следующие выходные данные b = False, i = 0 так как и b, и i автоматически инициализированы значениями по умолчанию. 10.5.5 Инициализаторы переменных Объявления полей могут включать инициализаторы_переменных;. Для статических полей инициализаторы переменных соответствуют операторам присваивания, выполняемым во время инициализации класса. Для полей экземпляров инициализаторы переменных соответствуют операторам присваивания, выполняемым при создании экземпляра класса. Пример. using System; class Test static void Main() { В этом примере производятся следующие выходные данные x = 1.4142135623731, i = 100, s = Hello так как присваивание для x происходит при выполнении инициализаторов статического поля, а присваивания для i и s происходят при выполнении инициализаторов поля экземпляра. Инициализация значения по умолчанию, описанная в §10.5.4, происходит для всех полей, включая поля, имеющие инициализаторы переменных. Таким образом, когда класс инициализируется, все статические поля в этом классе сначала инициализируются своими значениями по умолчанию, а затем выполняются инициализаторы статических полей в текстовом порядке. Аналогично, когда создается экземпляр класса, все поля в этом экземпляре сначала инициализируются своими значениями по умолчанию, а затем выполняются инициализаторы полей экземпляров в текстовом порядке. Статические поля с инициализаторами переменных можно наблюдать в их состоянии со значениями по умолчанию. Однако такой стиль настоятельно не рекомендуется. Пример. using System; class Test static void Main() { В этом примере показывается такое поведение. Несмотря на циклические определения a и b, программа допустима. Она дает на выходе a = 1, b = 2 так как статические поля a и b инициализированы значением 0 (значение по умолчанию для int) до выполнения их инициализаторов. Когда выполняется инициализатор для a, значение b равно нулю, так что a инициализируется значением 1. Когда выполняется инициализатор для b, значение a уже равно 1, так что b инициализируется значением 2. 10.5.5.1 Инициализация статического поля Инициализаторы переменных статических полей класса соответствуют последовательности присваиваний, выполняемых в текстовом порядке, в котором они появляются в объявлении класса. Если в классе существует статический конструктор (§10.12), выполнение инициализаторов статического поля происходит непосредственно перед выполнением этого статического конструктора. Иначе инициализаторы статических полей выполняются в зависящий от реализации момент перед первым использованием статического поля этого класса. Пример: using System; class Test
|