C#多线程和重新排序-这是怎么回事? - c#

我有以下代码:

    public static System.Int32 i = 0;

    static void Main(string[] args)
    {
        new Thread(Worker1) { IsBackground = true }.Start();
        new Thread(Worker2) { IsBackground = true }.Start();

        Console.WriteLine("Running... Press enter to quit");
        Console.ReadLine();
    }

    static void Worker1(object _)
    {
        while (true)
        {
            var oldValue = i;
            i++;
            var newValue = i;

            if (newValue < oldValue)
                Console.WriteLine("{2}, i++ went backwards! oldValue={0}, newValue={1}!", oldValue, newValue, DateTime.Now.ToString("HH:MM:ss.fff"));
        }
    }

    static void Worker2(object _)
    {
        while (true)
        {
            i++;
        }
    }

运行时,将产生如下所示的输出:

17:08:17.020, i++ went backwards! oldValue=6124653, newValue=6113984!
17:08:17.057, i++ went backwards! oldValue=18764535, newValue=18752368!
17:08:17.086, i++ went backwards! oldValue=27236177, newValue=27236176!
17:08:17.087, i++ went backwards! oldValue=27550457, newValue=27535008!
17:08:17.130, i++ went backwards! oldValue=40251349, newValue=40235492!
17:08:17.137, i++ went backwards! oldValue=42339974, newValue=42323786!
17:08:17.142, i++ went backwards! oldValue=43828602, newValue=43828436!
17:08:17.149, i++ went backwards! oldValue=45969702, newValue=45959111!
17:08:17.158, i++ went backwards! oldValue=48705847, newValue=48705549!
17:08:17.230, i++ went backwards! oldValue=71199684, newValue=71199674!

注意:这是在Windows 7上具有超线程的四核i7上运行的

据我所知,可以:

在oldValue和newValue的读取之间,Thread2增加了大约40亿倍(但不完全是!)。鉴于上述数字和时间,似乎我在接下来的2秒钟内有10次中奖机会更大。
CPU和编译器正在进行一些重新排序...这似乎是合乎逻辑的解释,但我无法完全弄清楚实际上可能导致这种情况的一系列操作?

任何人都可以阐明它吗?

为了澄清这个问题:作为教育活动的一部分,我正在故意寻找可复制内存重新排序错误的代码。有很多方法可以解决此问题,我主要是在分析正在发生的事情。

@Tymek已经显示了下面的答案(现已指出这一点非常明显)。

参考方案

您肯定知道i ++不是原子的,实际上看起来像这样:

从存储器中读取i到寄存器,
增加寄存器,
将寄存器写入i所在的内存,
返回i;

此序列可以在任何阶段中断。

考虑到这一点,以下一种情况会产生您的厄运信息:

让我们i100;
线程2读取100并被中断;
线程1执行一段时间,并将i递增到120(很少完整循环),然后将i读取为120,读取i并将其递增到121,并在var newValue = i;之前中断;
线程2将i递增到101并被中断;
线程一运行并执行var newValue = i <-这将在101中读取;

现在oldValue120,而newValue101

LeetCode题解计算机为什么是基于二进制的?

可以是三进制么?二进制有什么好处?题解:为什么叫电子计算机?算盘应该没有二进制

LeetCode题解统计城市的所有灯泡

这个是我刚毕业的时候,一个真实的面试题,这是一个开放题。题目描述:想办法,将一个城市的所有灯泡数量统计出来。题解:费米估算法1、如果某个城市常驻人口有1000万2、假设每5人居住在一套房里,每套房有灯泡5只,那么住宅灯泡共有1000万只3、假设公众场所每10人共享一只灯泡,那么共有100万只4、主要的这两者相加就得出了1100万只当然实际上这是估算的,具体应…

LeetCode题解黑白圆盘

一个圆盘被涂上了黑白二色,两种颜色各占一个半圆。圆盘以一个未知的速度、按一个未知的方向旋转。你有一种特殊的相机可以让你即时观察到圆上的一个点的颜色。你需要多少个相机才能确定圆盘旋转的方向?题解:可以用一个相机即可

LeetCode题解圆上任取三点构成锐角三角形的概率

来自字节跳动的一道几何题题解:1/4

LeetCode题解深度优先遍历和回溯的关系?

深度优先遍历的范围更大还是回溯的范围更大?为什么?题解:我的理解是:dfs是回溯思想的一种体现- 回溯:是在整个搜索空间中搜索出可行解,在搜索过程中不断剪枝回退,这是回溯的思想,这个搜索空间并没有限制于特定的数据结构。- dfs:dfs是指特定的数据结构中如图,树(特殊的图)中搜索答案,范围限制在了特定的数据结构。个人拙见。