Monitor vs lock

后端 未结 9 2120
孤独总比滥情好
孤独总比滥情好 2020-11-27 11:42

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

EDIT: It seems from th

相关标签:
9条回答
  • 2020-11-27 11:42

    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

    0 讨论(0)
  • 2020-11-27 11:56

    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.

    0 讨论(0)
  • 2020-11-27 12:01

    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.

    0 讨论(0)
  • 2020-11-27 12:02

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

    0 讨论(0)
  • 2020-11-27 12:03

    Lock Lock keyword ensures that one thread is executing a piece of code at one time.

    lock(lockObject)

            {
            //   Body
            }
    

    The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement and then releasing the lock

    If another thread tries to enter a locked code, it will wait, block, until the object is released.

    Monitor The Monitor is a static class and belongs to the System.Threading namespace.

    It provides exclusive lock on the object so that only one thread can enter into the critical section at any given point of time.

    Difference between Monitor and lock in C#

    The lock is the shortcut for Monitor.Enter with try and finally. Lock handles try and finally block internally Lock = Monitor + try finally.

    If you want more control to implement advanced multithreading solutions using TryEnter() Wait(), Pulse(), and PulseAll() methods, then the Monitor class is your option.

    C# Monitor.wait(): A thread wait for other threads to notify.

    Monitor.pulse(): A thread notify to another thread.

    Monitor.pulseAll(): A thread notifies all other threads within a process

    0 讨论(0)
  • 2020-11-27 12:04

    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);
    }
    
    0 讨论(0)
提交回复
热议问题