Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

10.5.3Поля с модификатором volatile

Если объявление_поля включает модификатор 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; using System.Threading;

class Test { public static int result; public static volatile bool finished;

static void Thread2() { result = 143; finished = true; }

static void Main() { finished = false;

// Run Thread2() in a new thread new Thread(new ThreadStart(Thread2)).Start();

// Wait for Thread2 to signal that it has a result by setting // finished to true. for (;;) { if (finished) { Console.WriteLine("result = {0}", result); return; } } } }

Для этого примера выходом является:

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 bool b; int i;

static void Main() { Test t = new Test(); Console.WriteLine("b = {0}, i = {1}", b, t.i); } }

В этом примере производятся следующие выходные данные

b = False, i = 0

так как и b, и i автоматически инициализированы значениями по умолчанию.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]