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();
}
}
最佳答案
- 如文档所述 - 如果它不使用任何锁,则此用法不会导致任何死锁。
- 假设您有一个通过从数据库中读取来初始化的惰性值,但您希望确保在任何时刻只有一个线程正在访问该数据库。如果您有其他访问数据库的代码,则可能会出现死锁。考虑以下代码:
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
在这种情况下也在内部使用锁,因此会导致死锁。
在这种情况下,通过将对 UpdateDb()
中的 lazyInt.Value
的访问移到 lock 语句之外,可以很容易地修复死锁,但它可能不会在其他情况下如此微不足道(或明显)。
关于c# - Lazy<T> ExecutionAndPublication - 可能导致死锁的示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6164434/