c# - Lazy<T> ExecutionAndPublication - 可能导致死锁的示例

标签 c# .net deadlock lazythreadsafetymode

LazyThreadSafetyMode 的文档声明如果初始化方法(或默认构造函数,如果没有初始化方法)在内部使用锁,则使用值 ExecutionAndPublication 可能会导致死锁。我试图更好地理解使用此值时可能导致死锁的示例。在我使用这个值时,我正在初始化一个 ChannelFactory .我看不到 ChannelFactory 的构造函数使用任何内部锁(使用 Reflector 查看类),所以我相信这种情况不符合可能的死锁情况,但我很好奇什么情况会导致死锁以及是否可能死锁初始化 ChannelFactory。

总而言之,我的问题是:

  1. 使用 ExecutionAndPublication 初始化 ChannelFactory 是否可能导致死锁?

  2. 使用 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();
    }
}

最佳答案

  1. 如文档所述 - 如果它不使用任何锁,则此用法不会导致任何死锁。
  2. 假设您有一个通过从数据库中读取来初始化的惰性值,但您希望确保在任何时刻只有一个线程正在访问该数据库。如果您有其他访问数据库的代码,则可能会出现死锁。考虑以下代码:
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/

相关文章:

c# - WCF 错误序列化循环引用

c# - 如何在 EPPLus 中设置 CSS 样式?

c# - 数组排序效率...初学者需要指点

c# - 我们如何在 Entity Framework 中进行对象过滤?

java - 为什么死锁没有发生?

c# - 事务死锁,如何设计得当?

python - Popen stdout 读取管道,使用 sleep 死锁

c# - 未为动态泛型解析方法

c# - 如何查看 C# 编译器生成的 MSIL/CIL?为什么叫组装呢?

javascript - 如何: Reset Bootstrap button state after returning a file from the controller