C# 全局迭代器的阻塞有意义吗?
我需要做一些事情,要求读取线程中的每个元素。 每个线程只需要读取元素C# 全局迭代器的阻塞有意义吗?,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,我需要做一些事情,要求读取线程中的每个元素。 每个线程只需要读取元素[i]并执行i++。我是否需要锁定i++ 我在某个地方读到,带有双变量的异步操作需要锁定以防止意外结果。我怎样才能告诉其他操作相同的情况?这里有问题操作的列表吗 更多细节。我有全局变量: public static int[] IntArray; public static int ArrayPointer = 0; 我以以下方式启动池中的一些线程: ThreadPool.QueueUserWorkItem(new WaitC
[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
}
该死,这是显而易见的,因为另一个线程可以突然执行
i++
,数组的某些元素将被跳过
所以只要:
static void ThreadMethod() {
//loop until ArrayPointer is too big
lock(LockObject) {
Console.WriteLine(IntArray[ArrayPointer]);
ArrayPointer++;
}
//end of loop
}
该死,这是显而易见的,因为另一个线程可以突然执行
i++
,数组的某些元素将被跳过
所以只要:
static void ThreadMethod() {
//loop until ArrayPointer is too big
lock(LockObject) {
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
您可以使用interlocted.Increment
以原子方式递增,但您仍然希望在循环的其余迭代中使用该递增操作的结果,而不是多次读取变量
实际上,我在此建议三件事:
- 不要为此使用静态变量。全局状态使代码难以测试和推理
- 将线程方面与其他方面隔离开来——将其封装在表现出更高级别行为的类中。如果您真的,真的需要全局状态,那么您可以拥有该类类型的静态只读变量,如果您愿意的话
- 尽量不要自己做太多低级的事情。NET有大量的并发编程选项,无论是“核心”TPL(支持异步/等待形式的语言)还是构建在其之上的类似东西。这些都是人们编写的积木,他们的主要工作是使这类东西坚如磐石,性能出众。不要试图自己做他们的工作:)
++
操作符执行读/修改/写操作。这个操作不是原子的,即使它的每个部分都是原子的
因此,您可以轻松地:
Thread 1 Thread 2
Read ArrayPointer (0)
Read ArrayPointer(0)
Increment locally (1)
Increment locally (1)
Write ArrayPointer (1)
Write ArrayPointer (1)
所以,尽管有两个增量,但结果是1
您可以使用interlocted.Increment
以原子方式递增,但您仍然希望在循环的其余迭代中使用该递增操作的结果,而不是多次读取变量
实际上,我在此建议三件事:
- 不要为此使用静态变量。全局状态使代码难以测试和推理
- 将线程方面与其他方面隔离开来——将其封装在表现出更高级别行为的类中。如果您真的,真的需要全局状态,那么您可以拥有该类类型的静态只读变量,如果您愿意的话
- 尽量不要自己做太多低级的事情。NET有大量的并发编程选项,无论是“核心”TPL(支持异步/等待形式的语言)还是构建在其之上的类似东西。这些都是人们编写的积木,他们的主要工作是使这类东西坚如磐石,性能出众。不要试图自己做他们的工作:)