从不同步的代码块调用对象同步方法

时间:2011-09-30 01:24:33

标签: c# .net synchronization

我在生产中收到一条异常,并在下面的代码中使用Mutex.ReleaseMutex()从“非同步代码块调用了对象同步方法”:

Mutex Mutex
{
    get { return mutex ?? (mutex = new Mutex(false, mutexName)); }
}
[NonSerialized]
Mutex mutex;

public void Log(/*...*/)
{
    Mutex.WaitOne();
    try
    {
        /*...*/
    }
    finally
    {
        Mutex.ReleaseMutex();
    }
}

可能有多个进程可以使用具有不同和相同mutextName的互斥锁。 而且我仍然不确定那里会发生异常。

1 个答案:

答案 0 :(得分:7)

此代码:

Mutex Mutex
{
    get { return mutex ?? (mutex = new Mutex(false, mutexName)); }
}

这不是线程安全的,可能会创建多个Mutex。使用假装时间,让我们看一下这个例子:

Thread A        |  Thread B
-------------------------------------
Enters
Is Null? (yes)   Enters
Create Mutex     Is Null? (yes) <- Thread A hasn't assigned it yet.
Assign mutex     Create Mutex
Use Mutex        Assign mutex  <- Oops! We just overwrote the mutex thread A created!
Release Mutex <- Oops! We are trying to release the mutex Thread B created without owning it!

希望插图不是垃圾。

使用System.Lazy<T>类是一种执行延迟初始化的线程安全方法,如果你真的想用你的互斥锁做这件事。

private Lazy<Mutex> _lazyMutex = new Lazy<Mutex>(() => new Mutex(false, "MyMutex"));
Mutex Mutex
{
    get { return _lazyMutex.Value; }
}

鉴于此,你为什么要试图懒惰初始化你的Mutex?你怎么处理它?<​​/ p>