如何使双重检查锁定语法更简洁?

时间:2009-07-30 14:56:23

标签: c# locking

在C#中,我有一个非常详细的语法,用于从数据库中提取一个简单的项目列表:

if (malls == null)
{
    lock (_lock)
    {
        if (malls == null)
        {
            using (var session = NhibernateHelper.OpenSession())
            {
                malls = session.CreateCriteria<Mall>()
                    .AddOrder(Order.Asc("Name")).List<Mall>();

                CacheManager.Set(CACHE_KEY, malls, TimeSpan.FromMinutes(CACHE_DURATION));
            }
        }
    }
}

我知道双重检查锁定的好处,我强烈支持它的使用,但它似乎非常冗长。你能推荐一些可能会清理它的语法快捷方式或样式吗?

2 个答案:

答案 0 :(得分:8)

大概你正在使用双重检查锁定,因为你有一个资源,你想以一种懒惰的线程安全的方式初始化。

双重检查锁定是一种机制来实现这一目标,但正如您已经正确指出的那样,该机制的详细程度彻底破坏了代码的含义。

当你有一种模糊含义的机制时,通过创建抽象来隐藏机制。一种方法是创建一个“懒惰线程安全实例化”类并将一个委托传递给它,它以懒惰的线程安全方式完成你想要的操作。

然而,有更好的方法。更好的方法是不要自己做这项工作,而是让一位世界级的线程专家为你做这件事。这样你就不用担心做对了。 Joe Duffy不得不担心做对。正如Joe明智地说的那样,不是在整个地方重复锁定机制,而是编写一次然后使用抽象。

Joe的代码在这里:

http://www.bluebytesoftware.com/blog/PermaLink,guid,a2787ef6-ade6-4818-846a-2b2fd8bb752b.aspx

此代码的变体将在下一版本的基类库中发布。

答案 1 :(得分:1)

要减少噪音,你可以这样做:

public List<Mall> Malls()
{
    EnsureMallsInitialized();
    return malls;
}

private void EnsureMallsInitialized()
{
    if (malls == null) // not set
    lock (_lock)       // get lock
    if (malls == null) // still not set
    {
        InitializeMalls();
    }        
}

private void InitializeMalls()
{
    using (var session = NhibernateHelper.OpenSession())
    {
        malls = session.CreateCriteria<Mall>()
            .AddOrder(Order.Asc("Name")).List<Mall>();

        CacheManager.Set(CACHE_KEY, malls, TimeSpan.FromMinutes(CACHE_DURATION));
    }
}