Threading text explanation in "C # 3.0 in a nutshell"

While reading C # 3.0 in a nutshell, Joseph and Ben Albahari came across the following paragraph (p. 673, first paragraph in the section entitled β€œ Alarm with Standby and Momentum ”)

β€œThe Monitor class provides a different signaling design through two static methods: Standby and Pulse . The principle is that you write the alarm logic yourself using custom flags and fields (enclosed in lock statements), and then enter the Standby and Pulse commands to reduce torque processor. The advantage of this low-level approach is that using wait Impulse and operator lock you can achieve AutoResetEvent functionality, and a ManualResetEvent Semaphore, as well as aticheskie methods of WaitHandle WaitAll and WaitAny strong>. In addition, the wait and the pulse can be seen in situations where expectations descriptors reserved challenged. "

My question is: what is the correct interpretation of the last sentence?

  • A situation with a decent / large number of wait descriptors, where WaitOne () only occasionally calls any particular wait descriptor.
  • A situation with a decent / large number of wait descriptors, where it rarely does more than one thread, is usually blocked on any particular wait descriptor.
  • Another interpretation.

I would also like to appreciate illustrative examples of such situations and, possibly, how and / or why they are more efficiently processed through Wait and Pulse, and not by other methods.

Thanks!

Edit: I found text online here

+7
multithreading wait waithandle pulse
source share
1 answer

This suggests that there are situations where Wait and Pulse provide a simpler solution than wait commands. In general, this happens where:

  • The waiter, not the notifier, decides when to unlock
  • The blocking condition includes a simpler flag (possibly several variables)

In these situations, you can still use wait descriptors, but Wait / Pulse tends to be simpler. The great thing about Wait / Pulse is that Wait releases the underlying lock while waiting. For example, in the following example, we read _x and _y within the security of the lock - and yet this lock is released while waiting for another thread to update these variables:

lock (_locker) { while (_x < 10 && _y < 20) Monitor.Wait (_locker); } 

Another thread can then update _x and _y atomically (due to blocking), and then Pulse to signal the waiter:

 lock (_locker) { _x = 20; _y = 30; Monitor.Pulse (_locker); } 

The disadvantage of Wait / Pulse is that it is easier to make a mistake and make a mistake (for example, updating a variable and forgetting the momentum). In situations where a wait-handling program is equally simple for a Wait / Pulse program, I would recommend going with wait commands for this reason.

In terms of efficiency / resource consumption (which I assume you pointed out), Wait / Pulse is usually faster and easier (since it has a managed implementation). However, this is rarely the case in practice. And at this point, Framework 4.0 includes the manually controlled versions of ManualResetEvent and Semaphore (ManualResetEventSlim and SemaphoreSlim).

Framework 4.0 also provides many additional synchronization options that reduce the need for Wait / Pulse:

  • CountdownEvent
  • Barrier
  • PLINQ / Data Parallelism (AsParallel, Parallel.Invoke, Parallel.For, Parallel.ForEach)
  • Tasks and Continuations

All of them are much higher than Wait / Pulse, and IMO is preferable for writing reliable and supported code (provided that they solve the problem at hand).

+5
source share

All Articles