仅当线程处于某种方法时才锁定多个方法

时间:2009-06-18 17:40:48

标签: c# .net multithreading locking

我有一个类(简化示例),如:

public class SomeCollection : ICloneable
{
    public void Add(Item item) { /* ... */ }
    public void Remove(Item item) { /* ... */ }
    public Item Get(Key key) { /* ... */ }
    /*
    ...
    */
    public object Clone() { /* ... */ }
}

我需要在线程进入Clone()时没有其他线程可以在Add或Remove中输入但可以输入Get。起初我想到了:

    public void Add(Item item) { lock(addLock) { /* ... */ } }
    public void Remove(Item item) { lock(removeLock) { /* ... */ } }

    public object Clone(Item item)
    { 
        lock(addLock)
        {
            lock(removeLock)
            {
                /* ... */
            }
        }
    }

这可行(我认为)但有一些缺点: *我不希望两个线程进入Add to block另一个 - 我正在处理更深层次的代码 *我必须承受每次调用Add或Remove

的锁定开销

然后我想到了这个

    private volatile bool cloning = false; // notice the volatile keyword

    public void Add(Item item)
    {
         int i = 0;
         while(cloning)
         { 
             if (i++ > 20)
                 throw new TimeoutException();
             Thread.Sleep(50); // waits 50 milliseconds
         }
         /* ... */
    } // and the same for Remove

    public object Clone()
    {
        cloning = true;
        try
        {
            /* do the cloning */
        } finally { cloning = false; }
    }

然而这种方法:

  • 更复杂
  • 当线程尚未执行添加或删除
  • 时,克隆可以进入
  • 似乎不自然

我给了ReadWriterLockSlim一眼,但似乎不适合我的情景。

我需要这个,因为克隆方法需要很长时间(可能需要一秒钟 - 集合是巨大的)并且此时的更改将炸毁枚举器(在foreach循环中使用)。是的,我必须使用foreach,因为底层密钥集合不会暴露除IEnumerable以外的任何东西。

推荐什么?

1 个答案:

答案 0 :(得分:1)

你能解释为什么ReaderWriterLockSlim不适合你的场景吗?

当然,您不会将它用于经典用途,但请将Clone方法视为您的编写者,并将添加/删除方法视为您的读者,我认为它适合。

[编辑]另一件事:如果你走这条路,请确保记录你向后使用ReaderWriterLockSlim的原因,以便下一个阅读代码的人(或者你在六个月内)了解正在发生的事情。< / p>