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

Временная запись и чтение

Теперь мы знаем, как процессорный кеш влияет на поведение приложений и что некоторые процессоры предлагают особые команды, предоставляющие программисту определенный контроль над согласованностью кеша. Познакомимся, как CLR позволяет задействовать преимущества этих команд. Ясно, что одна из основных задач CLR — предоставление абстрактной виртуальной машины, чтобы программисту не приходилось писать код, рассчитанный на какую-либо конкретную архитектуру процессора. Наиболее распространенный способ абстрагироваться от реализации для конкретного процессора — предоставить соответствующий метод. Класс System.Threading.Thread предлагает несколько статических методов, которые выглядят примерно так:

static Object VolatileRead(ref Object address);

static Byte VolatileRead(ref Byte address);

static SByte VolatileRead(ref SByte address);

static Int16 VolatileRead(ref Int16 address);

static UInt16 VolatileRead(ref UInt16 address);

static Int32 VolatileRead(ref Int32 address);

static UInt32 VolatileRead(ref UInt32 address);

static Int64 VolatileRead(ref Int64 address);

static UInt64 VolatileRead(ref UInt64 address);

static IntPtr VolatileRead(ref IntPtr address);

static UlntPtr VolatileRead(ref UIntPtr address);

static Single VolatileRead(ref Single address);

static Double VolatileRead(ref Double address);

static void VolatileWrite(ref Object address, Object value);

static void VolatileWrite(ref Byte address, Byte value);

static void VolatileWrite(ref SByte address, SByte value);

static void VolatileWrite(ref Int16 address, Int16 value);

static void VolatileWrite(ref UInt16 address, UInt16 value);

static void VolatileWrite(ref Int32 address, Int32 value);

static void VolatileWrite(ref UInt32 address, UInt32 value);

static void VolatileWrite(ref Int64 address, Int64 value);

static void VolatileWrite(ref UInt64 address, UInt64 value);

static void VolatileWrite(ref IntPtr address, IntPtr value);

static void VolatileWrite(ref UIntPtr address, UlntPtr value);

static void VolatileWrite(ref Single address, float value);

static void VolatileWrite(ref Double address, Double value);

static void MemoryBarrier();

Все методы VolatileRead выполняют чтение с семантикой запроса; они считывают значение, на которое ссылается параметр address, а затем объявляют недействительным кеш процессора. Все методы VolatileWrite выполняют запись с семантикой освобождения; они сбрасывают содержимое кеша в основную память, а затем изменяют значение, на которое ссылается параметр address, на значение аргумента value. Метод MemoryBarrier обеспечивает защиту памяти — он сбрасывает данные процессорного кеша в основную память, после чего объявляет кеш недействительным.

Теперь мы можем на основе кода класса CacheCoherencyProblem создать новый класс VolatileMethod:

internal sealed class VolatileMethod { private Byte uninitialized = 0; private Int32 m_value = 0;

// Этот метод выполняется одним потоком, public void Thread"!() {

m_value = 5;

Thread.VolatileWrite(ref uninitialized, 1);

// Этот метод выполняется другим потоком, publicvoidThread2() {

if (Thread.VolatileRead(ref uninitialized) == 1) {

// Если выполняется эта строка, отобразится значение 5.

Console.WriteLine(m_value);

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