Module 4: Monitors & Condition Synchronization Flashcards
Semaphore drawbacks
- Programmers gotta keep track of wait and signal. Thread has to release a lock before it dies.
- If the calls are done incorrectly => deadlocks.
- Unstructured => no encapsulation & data-hiding (not OOP).
- No connection: semaphore & data controlled by the semaphore.
- The multi-purpose of semahpores makes it difficult to identify what’s happening in the code
- Prone to bugs + hard to debug
How can Monitors be an alternative to semaphores?
- More structure
- Ties data, methods & sync as a class that encapsulates data & operations
- Solves problem of a global shared data. All data is private.
How does the monitor sync data?
- Threads trying to access shared data only interact through the monitor’s methods.
- Only 1 thread in the monitor at a time
The process of a thread entering the monitor
- Entering the monitor (“enters building”. queues in “entry hall”)
- Aquiring the monitor (“enters the room from the entry hall”)
- Owning the monitor (“locks the room” and owns the monitor)
- Releasing the monitor (releases the lock when “leaving the room”. Wait queue)
- Exiting the monitor (“leaves the building”, dequeues)
Thread waiting on a condition in a monitor
- Suspended thread = waits for an event to occur
- Releases monitor & waits
- Event occurs = thread is notified. Tries to aquire lock ASAP.
Why is a monitor good?
- Allows threads to have mutual exclusion (only 1 thread is active in the monitor at a time)
- Ability to suspend & have threads wait for a condition
- Encapsulates data & operations
What does a monitor encapsulate?
- Data: needs private variables (not outside monitor!)
- Methods: accessing shared data only in the monitor
- Synchronization: done thru condition variables (wait & signal capabilities)
How does a monitor ensure ME?
Each monitor has a lock and condition variable connected to it.
Condition variable in monitors
- Wait()
- Pulse()
- PulseAll()
Wait() condition variable
- If a resource not available, enter condition variable queue & sleep
- Releases monitor lock
Pulse() condition variable
- Wakes up a sleeping (waiting) thread
- Thread resumes its work after the lock is released
PulseAll() condition variable
- Wakes up ALL waiting threads
- Thread allowed to executed is up to CPU
- No thread waiting=> signal is lost
What is a condition variable?
- Container of threads waiting for a condition
- Type of queue, NOT boolean
- Like a place for threads to wait
- Waits or signals depending on the value
- Each monitor has 1 or several queues: waiting to enter and waiting after releasing.
- Queues are not directly visible to programmer
Thread or Monitor? Active and passive objects
- Active: Objects that initiate actions. Implemented as threads.
- Passive: Objects that respond to actions. Implemented as monitors.
- Airport EX:
- plane INITIATES action of arrival/departure (thread)
- control tower RESPONDS to arrival/departure (monitor)
Mutual Exclusion through monitor?
- No other thread will be in the executing region concurrently
- Threads in entry-set must compete to acquire monitor
- Threads in wait-set must compete to aquite monitor
- Required to: first arrive at entry, get monitor, then enter region.
In what way do monitors support both mutual exclusion & condition sync?
- ME: global lock. Mutex for all operations in monitor. Only one thread can execute in the monitor at a time.
- Condition sync: Condition variables provide sync. While a thread waits for an event to happen, other threads are allowed to execute.
How do waiting threads work in a monitor queue?
- Threads wait on condition variable queue until other thread signals
- Every monitor has a wait queue
- If a thread tries to enter the monitor when its in use: blocks.
- A suspended thread can reenter monitor when woken up (eg when a condition is met), resuming its work
What is condition synchronization?
- Coordination of multiple threads or processes in a way that allows them to cooperate & communicate with each other effectively
- A thread in CS => what if it can’t continue cuz a resource is lacking? Can release the lock & wait until resource is available.
- Think signaling with semaphores.
How does condition synchronization work in monitors?
- A thread may wanna sleep within a monitor, or allow a waiting thread to continue
- Monitors have a signaling mechanism too = tells waiting threads their condition has become true
- Condition variables provide sync within monitor => thread can wait & signal waiting threads to cont
- Thread can suspend (wait) itself to cooperate with other threads, letting them execute instead
What is the relationship between condition sync and condition variables?
- Condition sync is done by means of condition variables
- Condition variables are NOT booleans. They are DATA TYPES. Usually queue of waiting threads.
- Monitors use conditional variables to suspend & signal threads
What are the monitor methods in C#?
- Monitor.Enter(lockObj) = Aquire lock & enter
- Monitor.Exit(lockObj) = Release lock & exit
- Monitor.Pulse(lockObj) = Notify 1 waiting thread
- Monitor.PulseAll(lockObj) = Notify all waiting threads
- Monitor.Wait(lockObj) = Suspend itself for a condition to become true
- Monitor.TryEnter(lockObj) = Enters with a timeout time
How is a monitor structured in C#?
- Monitor has 2 items: critical section, condition variable
- It’s an abstract class
- Any object can be used as a monitor
object monitorObj = new object();
public double Method()
{
Monitor.Enter(monitorObj);
try
{
//critical section code
}
finally
{
Monitor.Exit(monitorObj);
}
}
}
Condition variables vs mutex
- A mutex controlls thread access to data
- Condition variables allow threads to sync based on ACTUAL value of data
- W/o condition variable => programmer has to continually check if condition is met (polling). Very resource consuming.
- Condition variable = same goal WITHOUT polling. Much better!
C# lock/Monitor example
- Can use lock(lockObj) instead of Monitor.Enter & Exit while still using the other methods (Wait, Pulse, PulseAll..)
lock(lockObj) //same as .Enter
{
while(IsFull)
{
//thread blocks
Monitor.Wait(lockObj);
}
//More code
Monitor.Pulse(lockObj);
} //same as .Exit = the lock releases here