Подтвердить что ты не робот

Разница между Interlocked.Exchange и Volatile.Write?

В чем разница между Interlocked.Exchange и Volatile.Write?

Оба метода обновляют значение некоторой переменной. Может кто-нибудь суммировать, когда использовать каждый из них?

http://msdn.microsoft.com/ru-ru/library/bb337971 и http://msdn.microsoft.com/en-us/library/gg712713.aspx

В частности, мне нужно обновить двойной элемент моего массива, и я хочу, чтобы другой поток увидел самое свежее значение. Что предпочтительнее? Interlocked.Exchange(ref arr[3], myValue) или Volatile.Write(ref arr[3], info);, где arr объявлен как double?

=============================================== ============================= Например, я объявляю двойной массив:

private double[] _cachedProduct;

В одном потоке я обновляю его так:

        _cachedProduct[instrumentId] = calcValue;
        ...
        are.Set();

В другом потоке я прочитал этот массив следующим образом:

        while(true) {
            are.WaitOne();
            ...
                result += _cachedProduct[instrumentId];
            ...
        }

Для меня это просто отлично работает. Однако, чтобы убедиться, что "он всегда будет работать", независимо от того, что мне кажется, я должен добавить либо Volatile.Write, либо Interlocked.Exchange. Поскольку двойное обновление не является атомарным http://msdn.microsoft.com/en-us/library/aa691278%28VS.71%29.aspx

В ответе на этот вопрос я хочу увидеть подробное сравнение летучих и блокированных классов. Почему нам нужны 2 класса? Какой и когда использовать?

4b9b3361

Ответ 1

Interlocked.Exchange использует инструкцию процессора, которая гарантирует атомную операцию.

Volatile.Write делает то же самое, но также включает в себя работу с защитой памяти. Я думаю, что Microsoft добавила Volatile.Write на DotNet 4.5 из-за поддержки процессоров ARM в Windows 8. Процессоры Intel и ARM отличаются от переупорядочения памяти.

В Intel у вас есть гарантия, что операции доступа к памяти будут выполняться в том же порядке, в каком они были выпущены, или, по крайней мере, что операция записи не будет переупорядочена.

В Руководстве разработчиков программного обеспечения Intel® 64 и IA-32, глава 8:

8.2.2 Заказ памяти в P6 и более новых семействах процессоров Семейство Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium 4 и P6 процессоры также используют упорядоченную по процессору модель памяти, которая может далее определяется как "запись, упорядоченная с пересылкой буфера хранилища". Эта модель может быть охарактеризована следующим образом.

В ARM у вас нет такой гарантии, поэтому необходим барьер памяти. Блог ARM, объясняющий это, можно найти здесь: http://blogs.arm.com/software-enablement/594-memory-access-ordering-part-3-memory-access-ordering-in-the-arm-architecture/

В вашем примере, поскольку операция с double не гарантируется быть атомарной, я бы рекомендовал блокировку для доступа к ней. Помните, что при чтении и настройке значения необходимо использовать блокировку для обеих частей кода.

Более полный пример будет лучше ответить на ваш вопрос, так как неясно, что происходит после того, как эти значения установлены. Для вектора, если у вас больше читателей, чем писателей, рассмотрите использование объекта ReaderWriterLockSlim: http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

Количество потоков и частота чтения/записи могут значительно изменить стратегию блокировки.