LazyThreadSafetyMode的文档指出,如果初始化方法(或默认构造函数,如果没有初始化方法)在内部使用锁,则使用值ExecutionAndPublication会导致死锁。我试图更好地理解使用此值时可能导致死锁的示例。在我使用此值时,我正在初始化ChannelFactory。我看不到ChannelFactory的构造函数使用任何内部锁(使用Reflector查看类),所以我认为这种情况不适合可能的死锁情况,但我很好奇什么情况可能导致死锁以及是否有可能死锁初始化ChannelFactory。
总而言之,我的问题是:
是否可能导致使用ExecutionAndPublication初始化ChannelFactory的死锁?
使用ExecutionAndPublication导致死锁初始化其他对象有哪些可能的方法?
假设您有以下代码:
class x
{
static Lazy<ChannelFactory<ISomeChannel>> lcf =
new Lazy<ChannelFactory<ISomeChannel>>(
() => new ChannelFactory<ISomeChannel>("someEndPointConfig"),
LazyThreadSafetyMode.ExecutionAndPublication
);
public static ISomeChannel Create()
{
return lcf.Value.CreateChannel();
}
}
答案 0 :(得分:10)
void Main()
{
Task otherThread = Task.Factory.StartNew(() => UpdateDb(43));
Thread.Sleep(100);
Console.WriteLine(lazyInt.Value);
}
static object l = new object();
Lazy<int> lazyInt = new Lazy<int>(Init, LazyThreadSafetyMode.ExecutionAndPublication);
static int Init()
{
lock(l)
{
return ReadFromDb();
}
}
void UpdateDb(int newValue)
{
lock(l)
{
// to make sure deadlock occurs every time
Thread.Sleep(1000);
if (newValue != lazyInt.Value)
{
// some code that requires the lock
}
}
}
Init()
从数据库读取,因此必须使用锁。 UpdateDb()
写入数据库,因此它也需要锁定,并且由于Lazy
在这种情况下也在内部使用锁,因此会导致死锁。
在这种情况下,通过在锁定语句之外移动lazyInt.Value
中UpdateDb()
的访问权限来修复死锁很容易,但在其他情况下可能不那么简单(或显而易见)