c# - 阻塞全局迭代器有意义吗?

标签 c# multithreading thread-safety

我需要做一些事情,要求读取线程中数组的每个元素。 每个线程只需要读取元素[i]并执行i++。我需要锁定 i++ 吗?

我在某处读到,使用双变量的异步操作需要锁定以防止出现意外结果。我怎么能告诉其他操作相同?这是有问题的操作列表吗?

更多细节。我有全局变量:

public static int[] IntArray;
public static int ArrayPointer = 0;

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

ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod));

像这样:

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

最佳答案

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

所以你可以轻松拥有:

Thread 1                 Thread 2

Read ArrayPointer (0)   
                         Read ArrayPointer(0)
Increment locally (1)
                         Increment locally (1)
Write ArrayPointer (1)
                         Write ArrayPointer (1)

因此,尽管有两个增量,但您得到的结果是 1。

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

我实际上会在这里建议三件事:

  • 不要为此使用静态变量。全局状态使代码难以测试和推理
  • 将线程方面与其他任何方面隔离 - 将其封装在表现出更高级别行为的类中。如果您真的非常需要全局状态,那么您可以根据需要使用该类类型的静态只读变量。
  • 尽量不要自己做太多底层的事情。 .NET 有大量的并发编程选项,无论是“核心”TPL(具有异步/等待形式的语言支持)还是类似 TPL Dataflow 的选项。建立在它之上。这些构建 block 是由那些主要工作是使这类东西坚如磐石和高性能的人编写的。不要试图自己完成他们的工作:)

关于c# - 阻塞全局迭代器有意义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28736084/

相关文章:

java - 静态内部类线程在另一个 java 类中是否安全?

c# - Xamarin SignaturePadView GetImage Android 黑色背景

c++ - Qt:这段代码中的QBuffer线程安全吗?

objective-c - 如何使用 Objective-C 获取正在运行的进程

c - 线程中的 sleep() 导致 main 也进入休眠状态

c++ - 双向链接的线程安全分离

java - java中读/写变量的原子操作

javascript - 在 Telerik RadPageView 完成加载后调用 JavaScript 函数?

c# - 带有用户添加字段的 .net 文本框

c# - Umbraco 通过别名查找内容