这个简单的缓存类是否需要线程同步?

时间:2010-05-26 10:20:22

标签: c#

这个简单的缓存类是否需要线程同步...如果我删除了锁_syncLock语句会遇到任何问题?我想我可以删除锁,因为引用应该正确更新吗? ... BUt我认为如果客户端代码迭代GetMyDataStructure方法并且它被替换,那么会发生什么?

编辑:我用TryGetValue样式方法替换了GetMyDataStructure并删除了所有锁定....这应该没问题吗?

    public bool TryGetValue(int id, out MyDataStructure myDataStructure)
    {
        return _cache.TryGetValue(id, out myDataStructure);
    }

谢谢!

public sealed class Cache 
{
    private readonly object _syncLock = new object();
    private IDictionary<int, MyDataStructure> _cache;

    public Cache()
    {
        Refresh();
    }

    public void Refresh()
    {
        lock (_syncLock)
        {
            _cache = DAL.GetMyDataStructure();
        }
    }

    public IDictionary<int, MyDataStructure> **GetMyDataStructure**()
    {
        lock (_syncLock)
        {
            return _cache;
        }
    }
}

4 个答案:

答案 0 :(得分:1)

由于对引用类型的赋值是原子的(参见C#标准的第5.5节),因此lock中不需要Refresh

至于锁定GetMyDataStructure,您实际上可能需要这样做 - 原因涵盖here。虽然我不太确定。

答案 1 :(得分:1)

Cache类实际上只告诉我们一个引用。这不是本身需要同步,因为它是原子的。然而!这实际上取决于调用者将使用字典。如果他们只阅读,那么它会起作用 - 但是如果他们中的任何一个要添加/删除/交换值那么它就会崩溃。

我很想暴露(而不是字典)一个带有类似索引器的不可变类型 - 所以没有调用者可以通过改变某些东西来破坏聚会。


编辑后;只有TryGetValue的版本不再使调用者能够破解它,所以应该没问题。

答案 2 :(得分:0)

我认为这是安全的,因为参考分配是原子的(除非存在隐式转换)。

答案 3 :(得分:0)

GetMyDataStructure中的锁几乎没有任何作用......

您最好考虑一下您将使用_cache的旧实例做什么,这些实例可以在您的代码中被设置为静态或其他长生命对象。真的,这将是地狱。不要使用这种方法。