我需要做一些事情,要求读取线程中数组的每个元素。
每个线程只需要读取元素[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/