6

这是一个只有我在编写和使用的小程序。

现在我将编写所有使用导致此问题的哈希集的区域的代码

我不明白这怎么可能。此项目仅在 MainWindow 中使用

hsProxyList 是一个哈希集

  HashSet<string> hsProxyList = new HashSet<string>();

错误发生在以下迭代中

 lock (hsProxyList)
            {
    int irRandomProxyNumber = GenerateRandomValue.GenerateRandomValueMin(hsProxyList.Count, 0);
    int irLocalCounter = 0;
    foreach (var vrProxy in hsProxyList)
    {
       if (irLocalCounter == irRandomProxyNumber)
       {
       srSelectedProxy = vrProxy;
       break;
       }
         irLocalCounter++;
       }
    }
}

我使用 hsProxyList 的其他地方

当我得到它的计数时,我没有锁定对象 - 我想这不会导致任何错误但可能不正确 - 不是致命的重要

 lblProxyCount.Content = "remaining proxy count: " + hsProxyList.Count;

新的

lock (hsProxyList)
{
    hsProxyList.Remove(srSelectedProxy);
}

新的

lock (hsProxyList)
{
    hsProxyList = new HashSet<string>();
    foreach (var vrLine in File.ReadLines(cmbBoxSelectProxy.SelectedItem.ToString()))
    {
        hsProxyList.Add(vrLine);
    }
}

可以看出我到处都在使用锁。这是一个多线程软件。所有 hsProxyList 都在 MainWindow.xaml.cs 中使用 - 它是一个 C# WPF 应用程序

4

2 回答 2

9

问题是你在哪里

lock (hsProxyList)
{
    hsProxyList = new HashSet<string>();
    // etc
}

所有锁都在特定对象上,但是当您更改对象时hsProxyList = new HashSet<string>();,变量 hsProxyList 引用的对象不再被锁定。

于 2013-05-26T14:05:36.857 回答
3

这里有两个问题。首先,已经指出的是,您锁定了哈希集,同时还将对象hsProxyList点更改为:

lock (hsProxyList)
{
    hsProxyList = new HashSet<string>();
    // hsProxyList is no longer locked.
}

第二个(也是更微妙的)问题是您假设Count不需要锁。这不是一个安全的假设。首先,你不知道HashSet它是如何实现的。Count是一个操作这一事实O(1)表明存在一个成员变量来跟踪计数。这意味着必须更新onAdd或此变量。Remove的实现Add可能类似于:

bool Add( T item ) {
    this.count++;
    // Point A.
    addItemToHashSet(item);
}

请注意,count变量会增加,然后添加项目。如果线程调用在点 AAdd被中断并且您调用的其他线程被执行,您将收到一个高于实际元素数量的计数(已增加,但未增加)。CountcountaddItemToHashSet

这可能不会产生任何严重的后果,但如果您对Count元素进行迭代,则可能会导致崩溃。调用时也可能出现类似行为Remove

于 2013-05-26T14:45:54.720 回答