Как я понимаю, модель памяти .NET на 32-разрядной машине гарантирует, что 32-разрядное слово записывает и читает как атомные операции, но не предоставить эту гарантию на 64-битные слова. Я написал быстрый инструмент для демонстрации этого эффекта на 32-разрядной ОС Windows XP, и я получаю результаты в соответствии с описанием этой модели памяти..NET 3.5SP1 64-разрядная модель памяти по сравнению с 32-разрядной моделью памяти
Тем не менее, я выполнил этот же исполняемый файл и запустил его на 64-разрядной ОС Windows 7 Enterprise и получаю совершенно разные результаты. Обе машины идентичны спецификациям только с установленными различными ОС. Я бы ожидал, что модель памяти .NET будет гарантировать запись и чтение BOTH 32-битных и 64-битных слов, которые будут атомарными в 64-битной ОС. Я нахожу результаты, полностью противоречащие BOTH-предположениям. 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;
}
}
}
Результатов на Windows XP 32-бите:
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-разрядная ОС.
Результаты на Windows 7 Enterprise 64-бит:
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 (длинный) и Бинг (интермедиат) оба отображаются! Почему сбой 32-разрядных операций, не говоря уже о 64-битных?
Возможно ли, что вы могли отредактировать свой вопрос, используя форматирование «Код образца» на панели инструментов? Это невероятно сложно читать .. – JBRWilkinson
Я правильно отформатировал его, но с символами TAB сначала вместо пробелов, и просмотр выглядел великолепно. Я был потрясен, когда обнаружил, что он полностью не смог опубликовать сообщение. Я исправил это сейчас. –
У меня уже было исправлено: D – Femaref