Call Thread.Sleep () inside a lock statement in .net

I was wondering if there would be a call to Threa.Sleep on the thread that the monitor had already acquired would release the lock before going to bed:

object o = new object(); Montior.Enter(o); Thread.Sleep(1000); Monitor.Exit(o); 

While the thread is paused - can another thread get o ?

+4
source share
4 answers

No, the lock will not be released if you sleep.

If you want to free it, use Monitor.Wait(o, timeout) ; in addition, you can also use this for a signal from another thread - another thread can use Monitor.Pulse[All] (holding the lock) to wake the waiting thread before the timeout (it will also close the lock again in this process )

Please note that whenever you use Enter / Exit, you should also use try / finally - or you are not at risk of releasing the lock if an exception occurs.

Example:

 bool haveLock = false; try { Monitor.Enter(ref haveLock); // important: Wait releases, waits, and re-acquires the lock bool wokeEarly = Monitor.Wait(o, timeout); if(wokeEarly) {...} } finally { if(haveLock) Monitor.Exit(o); } 

Another thread can do:

 lock(o) { Monitor.PulseAll(o); } 

Which will push any threads currently in Wait on this object (but will do nothing if the objects do not wake up). Emphasis: the waiting thread still has to wait until the impulse thread releases the lock, as it needs to be re-acquired.

+4
source

No, the thread will not release the lock before pausing / sleeping

and no other thread can get o until the sleeping thread wakes up and releases a locked object

+8
source

No, between Enter and Exit no other thread can block everything you do between them.

+7
source

In my experience, calling Thread.Sleep in the middle of a lock blocks the lock thread in order to lose the lock (e.g., context switch). I ran the following program:

  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; class Program { static void Main(string[] args) { Class1 c1 = new Class1(); Class2 c2 = new Class2(); Thread t1 = new Thread(c1.DoSomthing); Thread t2 = new Thread(c2.DoSomthing); t1.Start(); Thread.Sleep(500); t2.Start(); } } class Class1 { object m_objSyncLock = new object(); ManualResetEvent m_objSleep = new ManualResetEvent(true); public void DoSomthing() { Monitor.Enter(m_objSyncLock); int i = 1; //break point here Thread.Sleep(565); i++; //break point here Monitor.Exit(m_objSyncLock); } } } class Class2 { object m_objSyncLock = new object(); public void DoSomthing() { lock (m_objSyncLock) { int i = 1; //break point here i++; } } } 

Add breakpoints to lines 30, 32, 46 and notice that line 32 has first, then line 48, and only line 34. Doesn't that mean that calling Thread.Sleep made me lose my lock?

In addition, when using ManualResetEvent.WaitOne instead of Thread.Sleep, the executable thread does not lose its exclusivity (except for the switch directly to ManualResetEvent).

I am not a guru, but this simple test shows that Thread.Sleep can cause you to lose the lock when using ManualResetEvent.WaitOne synchronizes the block code block.

+3
source

Source: https://habr.com/ru/post/1398474/


All Articles