C# 读取和写入多线程共享数组

C# 读取和写入多线程共享数组,c#,multithreading,concurrency,thread-safety,task-parallel-library,C#,Multithreading,Concurrency,Thread Safety,Task Parallel Library,我有以下代码: const int MAX = 101; const int MIN_COMBINATORIC = 1000000; int[,] pascalTriangle = new int[MAX, MAX]; Parallel.For(0, MAX, i => { pascalTriangle[i, 0] = 1; pascalTriangle[i, i] = 1; }); int counter = 0; Parallel.For(0, MAX,

我有以下代码:

const int MAX = 101;
const int MIN_COMBINATORIC = 1000000;

int[,] pascalTriangle = new int[MAX, MAX];

Parallel.For(0, MAX, i =>
{
     pascalTriangle[i, 0] = 1;
     pascalTriangle[i, i] = 1;
}); 

int counter = 0;

Parallel.For(0, MAX, x => Parallel.For(1, x, y => 
{
      int value = pascalTriangle[x - 1, y] + pascalTriangle[x - 1, y - 1];
      Interlocked.Exchange(ref pascalTriangle[x, y], value < MIN_COMBINATORIC ? value : MIN_COMBINATORIC);
      if(value > MIN_COMBINATORIC)
          Interlocked.Increment(ref counter);
}));

Console.WriteLine("Result: {0}", counter);
const int MAX=101;
const int MIN_组合=1000000;
int[,]pascalTriangle=新int[MAX,MAX];
Parallel.For(0,MAX,i=>
{
帕斯卡尔三角形[i,0]=1;
帕斯卡尔三角形[i,i]=1;
}); 
int计数器=0;
Parallel.For(0,MAX,x=>Parallel.For(1,x,y=>
{
int值=帕斯卡尔三角形[x-1,y]+帕斯卡尔三角形[x-1,y-1];
联锁交换(参考帕斯卡尔三角形[x,y],值<最小组合?值:最小组合);
if(值>最小值组合)
联锁增量(参考计数器);
}));
WriteLine(“结果:{0}”,计数器);
问题是它有时打印出正确的答案(
Result:4075
),但有时打印出随机(错误)答案,例如:

  • 结果:2076
  • 结果:1771
  • 结果:0
我猜这与我在多个线程之间读写一个共享数组有关。 如您所见,我尝试为线程安全写入操作添加
Interlocked.exunge()
,但找不到类似的读取方法(有一个
Interlocked.Read()
,但它只能读取
long
变量)


如何使上述代码以线程安全的方式并发运行?

您应该研究在
Systems.Collections.Concurrent
命名空间中使用


如果BlockingCollection不适合您的需要,则此命名空间具有一系列不同类型的集合,这些集合都是线程安全的,如字典、堆栈、队列等。

您应该研究在
Systems.collections.Concurrent
命名空间中使用


如果BlockingCollection不适合您的需要,则此命名空间具有一系列不同类型的集合,这些集合都是线程安全的,如字典、堆栈、队列等。

您应该研究在
Systems.collections.Concurrent
命名空间中使用


如果BlockingCollection不适合您的需要,则此命名空间具有一系列不同类型的集合,这些集合都是线程安全的,如字典、堆栈、队列等。

您应该研究在
Systems.collections.Concurrent
命名空间中使用

如果BlockingCollection不适合您的需要,则此命名空间具有一系列不同类型的集合,这些集合都是线程安全的,如字典、堆栈、队列等。

中的值变量

int value = pascalTriangle[x - 1, y] + pascalTriangle[x - 1, y - 1];
依赖于数组中的两个项。由于并发性,这些值可以在添加这两个项、将它们存储到
value
中以及将该值传递到
Interlocked.Exchange
中之间进行更改。这意味着,当您在
pascalTriangle[x,y]
中存储
value
时,
pascalTriangle[x-1,y]
和/或
pascalTriangle[x-1,y-1]
中的值可能已经发生了变化

实际上,我想不出一个简单的并行解决方案。显而易见的解决办法是不要同时这样做。如果这是您想要使用的实际代码,那么并发运行它并没有真正的好处,因为它只循环101*101=10201次,这可以非常快地完成(初始化三角形的第一个并行代码只循环101次,因此也可以是单线程的)。如果像这样创建多个三角形,那么您可能会从并发创建三角形中获益(换句话说,创建三角形的方法是单线程的,但是调用方在单独的线程上多次调用此方法)

如果您真的想要一个并发解决方案,那么您需要弄清楚如何实现一种锁定机制,该机制可以锁定您正在访问的3个数组项,并且(困难的部分)以不会发生死锁的方式锁定它们。即使您提出了一个解决方案,所有锁的开销实际上可能会使代码比不同时执行的代码慢。

中的值变量

int value = pascalTriangle[x - 1, y] + pascalTriangle[x - 1, y - 1];
依赖于数组中的两个项。由于并发性,这些值可以在添加这两个项、将它们存储到
value
中以及将该值传递到
Interlocked.Exchange
中之间进行更改。这意味着,当您在
pascalTriangle[x,y]
中存储
value
时,
pascalTriangle[x-1,y]
和/或
pascalTriangle[x-1,y-1]
中的值可能已经发生了变化

实际上,我想不出一个简单的并行解决方案。显而易见的解决办法是不要同时这样做。如果这是您想要使用的实际代码,那么并发运行它并没有真正的好处,因为它只循环101*101=10201次,这可以非常快地完成(初始化三角形的第一个并行代码只循环101次,因此也可以是单线程的)。如果像这样创建多个三角形,那么您可能会从并发创建三角形中获益(换句话说,创建三角形的方法是单线程的,但是调用方在单独的线程上多次调用此方法)

如果您真的想要一个并发解决方案,那么您需要弄清楚如何实现一种锁定机制,该机制可以锁定您正在访问的3个数组项,并且(困难的部分)以不会发生死锁的方式锁定它们。即使您提出了一个解决方案,所有锁的开销实际上可能会使代码比不同时执行的代码慢。

中的值变量

int value = pascalTriangle[x - 1, y] + pascalTriangle[x - 1, y - 1];
依赖于数组中的两个项。由于并发性,这些值可以在添加这两个项、将它们存储到
value
中以及将该值传递到
Interlocked.Exchange
中之间进行更改。这意味着当您在
pascalTriangle[x,y]
中存储
value
时,
pascalTriangle[x-1,y]
和/或
pascalTriangle[x-1,y-1]
中的值可能会