Monitor vs lock

两盒软妹~` 提交于 2019-12-27 16:39:12

问题


When is it appropriate to use either the Monitor class or the lock keyword for thread safety in C#?

EDIT: It seems from the answers so far that lock is short hand for a series of calls to the Monitor class. What exactly is the lock call short-hand for? Or more explicitly,

class LockVsMonitor
{
    private readonly object LockObject = new object();
    public void DoThreadSafeSomethingWithLock(Action action)
    {
        lock (LockObject)
        {
            action.Invoke();
        }
    }
    public void DoThreadSafeSomethingWithMonitor(Action action)
    {
        // What goes here ?
    }
}

Update

Thank you all for your help : I have posted a another question as a follow up to some of the information you all provided. Since you seem to be well versed in this area, I have posted the link: What is wrong with this solution to locking and managing locked exceptions?


回答1:


Eric Lippert talks about this in his blog: Locks and exceptions do not mix

The equivalent code differs between C# 4.0 and earlier versions.


In C# 4.0 it is:

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

It relies on Monitor.Enter atomically setting the flag when the lock is taken.


And earlier it was:

var temp = obj;
Monitor.Enter(temp);
try
{
   body
}
finally
{
    Monitor.Exit(temp);
}

This relies on no exception being thrown between Monitor.Enter and the try. I think in debug code this condition was violated because the compiler inserted a NOP between them and thus made thread abortion between those possible.




回答2:


lock is just shortcut for Monitor.Enter with try + finally and Monitor.Exit. Use lock statement whenever it is enough - if you need something like TryEnter, you will have to use Monitor.




回答3:


A lock statement is equivalent to:

Monitor.Enter(object);
try
{
   // Your code here...
}
finally
{
   Monitor.Exit(object);
}

However, keep in mind that Monitor can also Wait() and Pulse(), which are often useful in complex multithreading situations.

Update

However in C# 4 its implemented differently:

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

Thanx to CodeInChaos for comments and links




回答4:


Monitor is more flexible. My favorite use case of using monitor is when you don't want to wait for your turn and just skip:

//already executing? forget it, lets move on
if(Monitor.TryEnter(_lockObject))
{
    //do stuff;
    Monitor.Exit(_lockObject);
}



回答5:


As others have said, lock is "equivalent" to

Monitor.Enter(object);
try
{
   // Your code here...
}
finally
{
   Monitor.Exit(object);
}

But just out of curiosity, lock will preserve the first reference you pass to it and will not throw if you change it. I know it's not recommended to change the locked object and you don't want to do it.

But again, for the science, this works fine:

var lockObject = "";
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
    tasks.Add(Task.Run(() =>
    {
        Thread.Sleep(250);
        lock (lockObject)
        {
            lockObject += "x";
        }
    }));
Task.WaitAll(tasks.ToArray());

...And this does not:

var lockObject = "";
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
    tasks.Add(Task.Run(() =>
    {
        Thread.Sleep(250);
        Monitor.Enter(lockObject);
        try
        {
            lockObject += "x";
        }
        finally
        {
            Monitor.Exit(lockObject);
        }
    }));
Task.WaitAll(tasks.ToArray());

Error:

An exception of type 'System.Threading.SynchronizationLockException' occurred in 70783sTUDIES.exe but was not handled in user code

Additional information: Object synchronization method was called from an unsynchronized block of code.

This is because Monitor.Exit(lockObject); will act on lockObject which has changed because strings are immutable, then you're calling it from an unsynchronized block of code.. but anyway. This is just a fun fact.




回答6:


Both are the same thing. lock is c sharp keyword and use Monitor class.

http://msdn.microsoft.com/en-us/library/ms173179(v=vs.80).aspx




回答7:


The lock and the basic behavior of the monitor (enter + exit) is more or less the same, but the monitor has more options that allows you more synchronization possibilities.

The lock is a shortcut, and it's the option for the basic usage.

If you need more control, the monitor is the better option. You can use the Wait, TryEnter and the Pulse, for advanced usages (like barriers, semaphores and so on).




回答8:


In addition to all above explanations, lock is a C# statement whereas Monitor is a class of .NET located in System.Threading namespace.



来源:https://stackoverflow.com/questions/4978850/monitor-vs-lock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!