在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));
}
}
}
}
我知道双重检查锁定的好处,我强烈支持它的使用,但它似乎非常冗长。你能推荐一些可能会清理它的语法快捷方式或样式吗?
答案 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));
}
}