Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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语言中的基本锁定问题#_C#_.net_Multithreading_Locking_Thread Safety - Fatal编程技术网

C# C语言中的基本锁定问题#

C# C语言中的基本锁定问题#,c#,.net,multithreading,locking,thread-safety,C#,.net,Multithreading,Locking,Thread Safety,课程包括: public class SomeCollection { public void IteratorReset() { index = -1; } public bool IteratorNext() { index++; return index < Count; } public int Count { get { return

课程包括:

public class SomeCollection
{
    public void IteratorReset()
    {
      index = -1;
    }

    public bool IteratorNext()
    {
      index++;
      return index < Count;
    }

    public int Count
    {
      get
      {
          return floatCollection.Count;
      }
    }

    public float CurrentValue
    {
      get
      {
        return floatCollection[index];
      }
    }

    public int CurrentIndex
    {
      get
      {
        return intCollection[index];
      }
    }
}
ClassA
ClassB
ClassC
包含以下循环,循环遍历CollectionObj:

for (threadUnsafeClass.CollectionObj.IteratorReset(); threadUnsafeClass.CollectionObj.IteratorNext(); )
{
    int currentIntIndex = threadUnsafeClass.CollectionObj.CurrentIndex;
    float currentfloatValue = threadUnsafeClass.CollectionObj.CurrentValue;

    // ...    
}
由于我只阅读这3个类中的CollectionObj,所以我使用多线程加速,但我不太确定如何加强线程安全性。在检索CollectionObj时,我在ThreadUnsaceClass中添加了一个锁,但是应用程序抛出了一个超出范围的异常

感谢您的帮助


谢谢大家!

您只读取了
CollectionObj
属性,但随后您对该值所引用的对象进行了变异。请看这一点:

for (threadUnsafeClass.CollectionObj.IteratorReset(); 
     threadUnsafeClass.CollectionObj.IteratorNext(); )
IteratorReset
iteratorext
都通过更改
index
的值来变异
SomeCollection
。基本上,使用当前代码无法安全地执行此操作。例如,多个线程都可以同时调用
IteratorNext()
。第一个调用返回
true
,但在该线程有机会读取值之前,其他线程会使索引无效


为什么要将集合本身用于迭代?通常,您需要实现
IEnumerable
,并在
GetEnumerator
中返回一个新对象。通过这种方式,不同的线程可以在同一集合上分别获得一个表示“它们的”光标的不同对象。他们都可以遍历它,并且都可以看到所有的值。

锁定CollectionObj属性不会有帮助。一个可能的问题是,所有3个线程都在调用
IteratorReset()
,这将索引设置为-1。想象一下这样的场景:A启动for循环,在被中断之前到达循环中的第一行。现在B进入并调用
IteratorReset()
,然后被中断,让A再次运行。线程A执行
CurrentIndex
属性,由于B正在运行,该属性在内部使用index=-1。动臂,超出范围异常


还有其他方法可以产生不好的结果,但这可能是最容易看到的。是否打算让所有三个线程各自完成每个项目?或者您是否希望A、B和C划分工作(如消费者队列)?

三个类A、B和C中的每个类都引用SomeCollection对象,每个类都将尝试增加内部索引,从而导致错误。也就是说,您应该能够通过以下方式从多个线程读取数组中的对象:

public static object[] sharedList = new object[]{1,2,3,4,5};
public void Worker()
{
   int localSum=0;
   for(int i=0; i<sharedList.length; i++){
      localSum += (int)sharedList[i];
   }
}
publicstaticobject[]sharedList=newobject[]{1,2,3,4,5};
公职人员()
{
int localSum=0;

对于(int i=0;我感谢您的回答。所有线程都将在集合中的相同项上迭代。如果是这种情况,最好按照Jon Skeet的建议执行。如果您需要每个线程分割工作,可以更改SomeCollection的实现以在GetNext()上返回元组,在关键部分锁定该方法的实现。谢谢Jon。在GetEnumerator()中返回新对象会有什么影响考虑到我的集合通常非常大,循环部分被调用数十万次,对性能有什么影响?@alhazen:如果集合非常大,这将减少创建额外对象的影响-因为您不会在每次迭代中创建一个对象,整个循环只创建一次。如果确实需要,可以使用值类型想要,就像
List
一样-但在你知道有问题之前我绝对不会这么做。很抱歉再次打扰你。我修改了
SomeCollection
,以便它按照你的建议实现
IEnumerable
。当前GetEnumerator()返回
floatListCollection.GetEnumerator()
但我找不到一篇文章描述每次调用时返回新枚举数对象的方法。在这种情况下我可以使用克隆吗?谢谢。
public static object[] sharedList = new object[]{1,2,3,4,5};
public void Worker()
{
   int localSum=0;
   for(int i=0; i<sharedList.length; i++){
      localSum += (int)sharedList[i];
   }
}