阻塞全局迭代器是否有意义?

Inf*_*eus 1 c# multithreading thread-safety

我需要做一些要求读取线程中arrey的每个元素的东西.每个线程只需要阅读元素[i]i++.我需要锁i++吗?

我在某处读到带有双变量的异步操作需要锁定以防止意外结果.我怎么能对另一个操作说同样的话?以下是有问题的操作列表?

有关更多细节.我有全局变量:

public static int[] IntArray;
public static int ArrayPointer = 0;
Run Code Online (Sandbox Code Playgroud)

我以这种方式在池中启动一些线程:

ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod));
Run Code Online (Sandbox Code Playgroud)

像这样:

static void ThreadMethod() {
  //loop until ArrayPointer is too big
  Console.WriteLine(IntArray[ArrayPointer]);
  ArrayPointer++;
  //end of loop
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

这里重要的是你有一个共享变量,++操作符执行读/修改/写操作.该操作不是原子操作,即使它的每个部分都是原子的.

所以你可以轻松拥有:

Thread 1                 Thread 2

Read ArrayPointer (0)   
                         Read ArrayPointer(0)
Increment locally (1)
                         Increment locally (1)
Write ArrayPointer (1)
                         Write ArrayPointer (1)
Run Code Online (Sandbox Code Playgroud)

所以尽管有两个增量,你的结果为1.

您可以使用Interlocked.Increment原子增量,但是您仍然希望在循环的其余迭代中使用该增量操作的结果,而不是多次读取变量.

我实际上会在这里提出三件事:

  • 不要为此使用静态变量.全局状态使代码难以测试且难以推理
  • 将线程方面与其他任何方面隔离开来 - 将其封装在具有更高级别行为的类中.如果你确实需要全局状态,那么你可以拥有该类类型的静态只读变量,如果你愿意的话.
  • 尽量不要自己做太多低级别的东西..NET提供了大量的并发编程选项,无论是"核心"TPL(以async/await形式提供语言支持)还是构建在其上的TPL Dataflow.这些是由人们编写的构建块,其主要工作是使这种东西变得坚固和高效.不要试图自己做他们的工作:)