gpt4 book ai didi

c# - 尝试在 .NET 中捕获内存重新排序

转载 作者:行者123 更新时间:2023-11-30 21:53:43 25 4
gpt4 key购买 nike

我有一个有点奇怪的程序,我试图在 .NET 中捕获一些内存重新排序:

private static volatile int x, y;
private static int b = -1;
private static int a = -1;

static void Main()
{
Run();
}

public static void Run()
{
Random rand = new Random();
var time = DateTime.Now;
while ((a != 0 || b != 0))
{
int t1StartId = rand.Next(1, 10);
int t2StartId = rand.Next(1, 10);

Thread t1 = new Thread(RunOne);
Thread t2 = new Thread(RunTwo);

for (int i = 0; i <= 10; i++)
{
if (t1StartId == i)
{
t1.Start();
}

if (t2StartId == i)
{
t2.Start();
}
}

t1.Join();
t2.Join();
x = 0;
y = 0;
}

Console.WriteLine("Memory Reordered!!!!!!!!!!!!!!!!!!!!!");
Console.WriteLine("Time Taken: {0}", DateTime.Now - time);
}

static void RunOne()
{
x = 1;
a = y;
}

static void RunTwo()
{
y = 1;
b = x;
}
}

现在,根据我一直在做的阅读(herehereherehere),在每个线程完成执行后,a 和 b *应该都可能等于 0。有人能证实这一点吗?我的任何操作是否在我不知道的场景下呈现内存屏障,哪些会阻止重新排序并因此保持无限循环?

我在 x86 CPU 上运行它,我怀疑这也会对结果产生影响。

编辑:

所以在多次运行程序后,它现在脱离了循环:

enter image description here

我仍然不相信这是内存重新排序的结果。

第二次运行:

enter image description here

如此决定性的问题! - 这真的是内存重新排序的结果,还是其他原因?

最佳答案

是的,您的示例演示了内存重新排序。我无法自己重现它,但这可能是我特定设置的结果。

我将使用向下箭头 ↓ 表示 volatile 读取,使用向上箭头 ↑ 表示 volatile 写入。将箭头视为推开任何其他读取和写入。只要没有指令通过向下箭头向上和通过向上箭头向下,生成这些内存栅栏的代码就可以自由移动。然而,内存栅栏(箭头)被锁定在它们最初在代码中声明的位置。因此,使用图示的围栏重现您的代码将如下所示。

static void RunOne()
{
↑ // volatile write fence
x = 1;
var register = y;
↓ // volatile read fence
a = register;
}

static void RunTwo()
{
↑ // volatile write fence
y = 1;
var register = x;
↓ // volatile read fence
b = register;
}

所以你可以看到,在RunOne中,对x的写入和对y的读取是可以合法交换的。类似地,在 RunTwo 中,写入 y 和读取 x 也可以合法交换。

您使用 x86 架构的事实对这个示例没有任何影响,因为 volatile 写入后跟 volatile 读取是 x86 强内存模型中唯一仍然允许交换的安排。

关于c# - 尝试在 .NET 中捕获内存重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33715877/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com