【问题标题】:C# multi-threading code reviewC# 多线程代码审查
【发布时间】:2009-05-12 02:15:04
【问题描述】:

锁定队列重要吗?

public abstract class ExpiringCache<TKey,TValue> : IDisposable 
{
    protected readonly object locker = new object();

    protected readonly Dictionary<TKey, TValue> cache =
        new Dictionary<TKey, TValue>();

    private readonly Queue<KeyValuePair<TKey, long>> queue =
        new Queue<KeyValuePair<TKey, long>>();

    private volatile bool dispose;

    private readonly Thread cleaningThread;

    private readonly long lifeSpanTicks;

    public ExpiringCache(TimeSpan lifeSpan)
    {
        // Validate lifeSpan

        if (lifeSpan.Ticks == 0)
        {
            throw new ArgumentOutOfRangeException
                ("lifeSpan", "Must be greater than zero.");
        }

        this.lifeSpanTicks = lifeSpan.Ticks;

        // Begin expiring expired items

        this.cleaningThread = new Thread(() =>
        {
            while (!this.dispose)
            {
                this.RemoveExpired();
                Thread.Sleep(1);
            }
        });

        this.cleaningThread.Start();
    }

    private void RemoveExpired()
    {
        if (this.queue.Count == 0)
        {
            return;
        }

        var pair = this.queue.Peek();

        if (pair.Value >= DateTime.Now.Ticks)
        {
            lock (this.locker)
            {
                this.cache.Remove(pair.Key);
            }

            this.queue.Dequeue();
        }
    }

    public bool Contains(TKey key)
    {
        lock (this.locker)
        {
            return this.cache.ContainsKey(key);
        }
    }

    public void Add(TKey key, TValue value)
    {
        lock (this.locker)
        {
            this.cache.Add(key, value);
        }

        this.queue.Enqueue(new KeyValuePair<TKey, long>
            (key, DateTime.Now.Ticks + this.lifeSpanTicks));
    }

    public void Dispose()
    {
        this.dispose = true;
    }
}

【问题讨论】:

  • 你有没有考虑过使用 Wea​​kReferences 让 GC 处理对象死亡?
  • 是否从缓存中检索过任何内容?
  • 关于缺少的 Get() 方法,我们应该假设有比这更多的方法来检索项目,但 OP 认为显示它们没有用。或者它们在子类中使用,因为它们被声明为受保护的。无论哪种方式,这都不是问题的一部分。
  • @DonkeyMaster 我不同意,如果这是一次代码审查,那么所有代码​​以及类的使用和派生方式都很重要。

标签: c# multithreading locking


【解决方案1】:

例如,仅锁定 Contains 方法是不够的。看到这个:
http://blogs.msdn.com/jaredpar/archive/2009/02/16/a-more-usable-thread-safe-collection.aspx

基本上,您需要重新考虑经典的 Queue API 并使用像 DequeueIfContains() 这样的方法,而不是简单的 Contains() + Dequeue(),以便相同的锁适用于 Contains 检查和 @987654326 @操作。

【讨论】:

  • 乔尔虽然我不同意你所说的,但队列似乎只是为了清理。代码中没有 Get() 方法从缓存中检索项目,只有一个 Contains() 来查看它们是否在缓存中。
【解决方案2】:

您可以使用:ConcurrentDictionary&lt;TKey, TValue&gt;ConcurrentQueue&lt;T&gt;。它们内置于 C# .Net 4.0 及更高版本中。

【讨论】:

  • 从 .Net 4.0 开始
猜你喜欢
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多