Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 全局迭代器的阻塞有意义吗?_C#_Multithreading_Thread Safety - Fatal编程技术网

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(支持异步/等待形式的语言)还是构建在其之上的类似东西。这些都是人们编写的积木,他们的主要工作是使这类东西坚如磐石,性能出众。不要试图自己做他们的工作:)

您先是怎么做的?(即:显示一些代码)您首先是如何操作的?(即:显示一些代码)正如我所怀疑的。非常感谢。如果您期望出现意外的行为,它是否会使行为成为预期的行为?:)正如我所怀疑的。非常感谢。如果您期望出现意外的行为,它是否会使行为成为预期的行为?:)