为什么Monitor.Enter / Exit与lock()语句相比不可靠?

时间:2017-01-13 08:34:57

标签: .net multithreading

using System.Collections.Concurrent;
using System.Threading;

namespace Examino.Infrastructure
{
    public class MutexProviderService : IMutexProviderService
    {
        private readonly ConcurrentDictionary<string, object> mutexCollection;

        public MutexProviderService()
        {
            mutexCollection = new ConcurrentDictionary<string, object>();
        }

        public void Enter(string key)
        {
            Monitor.Enter(GetMutex(key));
        }

        public void Exit(string key)
        {
            Monitor.Exit(GetMutex(key));
        }

        public object GetMutex(string key)
        {
            return mutexCollection.GetOrAdd(key, (s) => new object());
        }
    }

    public interface IMutexProviderService
    {
        object GetMutex(string key);
        void Enter(string key);
        void Exit(string key);
    }
}

我通过多个TPL任务测试这个类,并看到

lock (mutexProviderService.GetMutex(lockName)) {}

可靠地锁定关键部分和

mutexProviderService.Enter(lockName);
try { }
finally
{
    mutexProviderService.Exit(lockName);
}

不可靠。手动调用使用相同实例参数调用definitelly的Enter / Exit有什么问题? 附:来自MSDN的命名互斥代码比这个类要大得多,也更复杂。

1 个答案:

答案 0 :(得分:0)

这实际上不是您问题的答案,但从c#4.0开始,lock会生成下一个代码(阅读this文章):

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    { body }
}
finally
{
    if (lockWasTaken) Monitor.Exit(temp);
}