从多个线程同时向全局变量添加值?

Mus*_*ici 2 .net c# multithreading

如何同时为变量添加值?如果可以的话会是什么结果?崩溃还是其他什么?
例如:

int a;
Run Code Online (Sandbox Code Playgroud)


所以将有 2 个线程来增加一次价值。
谢谢

Jar*_*Par 5

当 2 个线程在没有任何同步的情况下添加到共享值时的行为是未定义的。写入不会导致任何类型的崩溃。它只会将该值作为其中一个线程所见的最终值

为了获得定义的行为,您需要添加某种同步,例如锁。

internal static class Holder {
  static object m_lock = new object();
  static int a;
  internal static void Add(int value) {
    lock (m_lock) {
      a += value;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 5

如果您以不受控制的方式执行此操作,很可能会丢失数据。

每个线程将采取三个步骤:

  • 读取值
  • 增加副本
  • 存储增加的值

如果他们都大致一起执行第一步,结果将是增量 1 而不是 2。

此外,存在内存模型问题,其中一个线程可能无法“看到”另一个线程的写入。记忆模型是复杂的野兽...

使用Interlocked.Increment执行原子递增,其中还使用易失性存储器访问,以确保它总是能看到什么其他的线程都写。

损坏的代码示例:

using System;
using System.Threading;

class Test
{
    const int Iterations = 1000000;

    static int counter;


    static void Main()
    {
        Thread t1 = new Thread(AddLots);
        t1.Start();
        AddLots();
        t1.Join();
        Console.WriteLine(counter);
    }

    static void AddLots()
    {
        for (int i = 0; i < Iterations; i++)
        {
            // Broken!
            counter++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

刚刚在我的笔记本电脑上运行,显示结果为 1011788。

改变这一行:

counter++;
Run Code Online (Sandbox Code Playgroud)

对此:

Interlocked.Increment(ref counter);
Run Code Online (Sandbox Code Playgroud)

这一切都很好。