.NET 3.5SP1 64-разрядная модель памяти по сравнению с 32-разрядной моделью памяти

Насколько я понимаю модель памяти.NET на 32-разрядной машине гарантирует 32-разрядные записи слова и читает, чтобы быть атомарными операциями, но не обеспечивает эту гарантию на 64-разрядных словах. Я записал быстрый инструмент для демонстрации этого эффекта на Windows XP 32-разрядная ОС, и получаю результаты, согласовывающиеся с тем описанием модели памяти.

Однако я взял исполняемый файл этого того же инструмента и выполнил его на Предприятии Windows 7 64-разрядная ОС, и получаю дико различные результаты. Оба машины являются идентичными спецификациями только с различными установленными Ose. Я ожидал бы, что модель памяти.NET гарантирует записи и чтения и к 32-разрядным и к 64-разрядным словам, чтобы быть атомарной на 64-разрядной ОС. Я нахожу результаты полностью вопреки ОБОИМ предположениям. 32-разрядные чтения и записи не продемонстрированы, чтобы быть атомарными на этой ОС.

Кто-то может объяснить мне, почему это перестало работать на 64-разрядной ОС?

Код инструмента:

using System;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var th = new Thread(new ThreadStart(RunThread));
            var th2 = new Thread(new ThreadStart(RunThread));
            int lastRecordedInt = 0;
            long lastRecordedLong = 0L;
            th.Start();
            th2.Start();
            while (!done)
            {
                int newIntValue = intValue;
                long newLongValue = longValue;
                if (lastRecordedInt > newIntValue) Console.WriteLine("BING(int)! {0} > {1}, {2}", lastRecordedInt, newIntValue, (lastRecordedInt - newIntValue));
                if (lastRecordedLong > newLongValue) Console.WriteLine("BING(long)! {0} > {1}, {2}", lastRecordedLong, newLongValue, (lastRecordedLong - newLongValue));
                lastRecordedInt = newIntValue;
                lastRecordedLong = newLongValue;
            }
            th.Join();
            th2.Join();
            Console.WriteLine("{0} =? {2}, {1} =? {3}", intValue, longValue, Int32.MaxValue / 2, (long)Int32.MaxValue + (Int32.MaxValue / 2));
        }

        private static long longValue = Int32.MaxValue;
        private static int intValue;
        private static bool done = false;

        static void RunThread()
        {
            for (int i = 0; i < Int32.MaxValue / 4; ++i)
            {
                ++longValue;
                ++intValue;
            }
            done = true;
        }
    }
}

Результаты на 32-разрядном Windows XP:

Windows XP 32-bit
Intel Core2 Duo P8700 @ 2.53GHz
BING(long)! 2161093208 > 2161092246, 962
BING(long)! 2162448397 > 2161273312, 1175085
BING(long)! 2270110050 > 2270109040, 1010
BING(long)! 2270115061 > 2270110059, 5002
BING(long)! 2558052223 > 2557528157, 524066
BING(long)! 2571660540 > 2571659563, 977
BING(long)! 2646433569 > 2646432557, 1012
BING(long)! 2660841714 > 2660840732, 982
BING(long)! 2661795522 > 2660841715, 953807
BING(long)! 2712855281 > 2712854239, 1042
BING(long)! 2737627472 > 2735210929, 2416543
1025780885 =? 1073741823, 3168207035 =? 3221225470

Заметьте, как Bing (интервал) никогда не пишется и демонстрирует, что 32-разрядные чтения/записи являются атомарными на этой 32-разрядной ОС.

Результаты на 64-разрядном предприятии Windows 7:

Windows 7 Enterprise 64-bit
Intel Core2 Duo P8700 @ 2.53GHz
BING(long)! 2208482159 > 2208121217, 360942
BING(int)! 280292777 > 279704627, 588150
BING(int)! 308158865 > 308131694, 27171
BING(long)! 2549116628 > 2548884894, 231734
BING(int)! 534815527 > 534708027, 107500
BING(int)! 545113548 > 544270063, 843485
BING(long)! 2710030799 > 2709941968, 88831
BING(int)! 668662394 > 667539649, 1122745
1006355562 =? 1073741823, 3154727581 =? 3221225470

Заметьте, что Bing (долго) И Bing (интервал) оба отображены! Почему 32-разрядные операции перестали работать, уже не говоря о 64-разрядных?

5
задан James Dunne 7 June 2010 в 16:58
поделиться

1 ответ

В обратном вызове потока вы делаете гораздо больше, чем просто запись или чтение:

++longValue;
++intValue;

Выполнение и чтения, и записи не может быть гарантировано атомарным. Используйте Interlocked.Increment , чтобы гарантировать атомарность этой операции.

4
ответ дан 15 December 2019 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: