net 3.5SP1 64位内存模型和32位内存模型

时间:2022-09-01 10:18:38

As I understand it, the .NET memory model on a 32-bit machine guarantees 32-bit word writes and reads to be atomic operations but does not provide this guarantee on 64-bit words. I have written a quick tool to demonstrate this effect on a Windows XP 32-bit OS and am getting results consistent with that memory model description.

正如我所理解的,在32位机器上的. net内存模型保证32位字的写入和读取是原子操作,但不提供64位字的这种保证。我编写了一个快速工具来演示Windows XP 32位操作系统的这种效果,并得到与内存模型描述一致的结果。

However, I have taken this same tool's executable and run it on a Windows 7 Enterprise 64-bit OS and am getting wildly different results. Both the machines are identical specs just with different OSes installed. I would have expected that the .NET memory model would guarantee writes and reads to BOTH 32-bit and 64-bit words to be atomic on a 64-bit OS. I find results completely contrary to BOTH assumptions. 32-bit reads and writes are not demonstrated to be atomic on this OS.

然而,我使用了相同的工具的可执行文件,并在Windows 7企业64位操作系统上运行,得到的结果大相径庭。这两台机器都是相同的规格,只是安装了不同的操作系统。我本以为。net内存模型会保证对32位和64位字的写和读在64位操作系统上都是原子的。我发现结果与这两个假设完全相反。32位的读写在这个操作系统上没有被证明是原子的。

Can someone explain to me why this fails on a 64-bit OS?

有人能解释一下为什么在64位操作系统上失败吗?

Tool code:

工具代码:

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;
        }
    }
}

Results on Windows XP 32-bit:

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

Notice how BING(int) is never written and demonstrates that 32-bit reads/writes are atomic on this 32-bit OS.

请注意BING(int)是如何从未被写入的,并演示了32位读/写在这个32位操作系统上是原子的。

Results on Windows 7 Enterprise 64-bit:

Windows 7企业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

Notice that BING(long) AND BING(int) are both displayed! Why are the 32-bit operations failing, let alone the 64-bit ones?

注意,BING(long)和BING(int)都显示出来了!为什么32位操作失败了,更不用说64位操作了?

1 个解决方案

#1


4  

In your thread callback you are doing much more than simply writing or reading:

在您的线程回调中,您所做的不仅仅是简单地编写或读取:

++longValue;
++intValue;

Doing both reading and writing cannot be guaranteed to be atomic. Use Interlocked.Increment to ensure atomicity of this operation.

既读又写不能保证是原子性的。使用联锁。增加以确保操作的原子性。

#1


4  

In your thread callback you are doing much more than simply writing or reading:

在您的线程回调中,您所做的不仅仅是简单地编写或读取:

++longValue;
++intValue;

Doing both reading and writing cannot be guaranteed to be atomic. Use Interlocked.Increment to ensure atomicity of this operation.

既读又写不能保证是原子性的。使用联锁。增加以确保操作的原子性。