150 likes | 254 Views
CS162 Section 2. True/False. A thread needs to own a semaphore, meaning the thread has called semaphore.P (), before it can call semaphore.V () False: Any thread with a reference to the semaphore can call V(). True/False.
E N D
True/False • A thread needs to own a semaphore, meaning the thread has called semaphore.P(), before it can call semaphore.V() • False: Any thread with a reference to the semaphore can call V()
True/False • A thread needs to own the monitor lock before it can signal() a condition variable. • True: A thread must acquire the monitor lock before it can access any of the monitor’s state.
True/False • Anything that can be done with monitors can also be done with semaphores. • True: Since monitors can be implemented using semaphores.
StackOverflow Analogy A monitor is like a public toilet. Only one person can enter at a time. They lock the door to prevent anyone else coming in, do their stuff, and then unlock it when they leave.
Short Answer • Give two reasons why the following implementation of a condition variable is incorrect (assume that MySemi is a semaphore initialized to 0): Wait() { MySemi.P(); } Signal() { MySemi.V(); } • Reason 1: Semaphores are commutative, while condition variables are not. Practically speaking, if someone executes MySemi.V() followed by MySemi.P(), the latter will not wait. In contrast, execution of Signal() before Wait() should have no impact on Wait().
Short Answer • Give two reasons why the following implementation of a condition variable is incorrect (assume that MySemi is a semaphore initialized to 0): Wait() { MySemi.P(); } Signal() { MySemi.V(); } • Reason 2: The above implementation of Wait() will deadlock the system if it goes to sleep on MySemi.P() (since it will go to sleep while holding the monitor lock).
Condition Variables • Condition Variable: a queue of threads waiting for something inside a critical section • Key idea: allow sleeping inside critical section by atomically releasing lock at time we go to sleep • Contrast to semaphores: Can’t wait inside critical section • Operations: • Wait(&lock): Atomically release lock and go to sleep. Re-acquire lock later, before returning. • Signal(): Wake up one waiter, if any • Broadcast(): Wake up all waiters • Rule: Must hold lock when doing condition variable ops!
Complete Monitor Example (with condition variable) • Here is an (infinite) synchronized queue Lock lock;Condition dataready; Queue queue; AddToQueue(item) { lock.Acquire(); // Get Lock queue.enqueue(item); // Add itemdataready.signal();// Signal any waiters lock.Release(); // Release Lock } RemoveFromQueue() { lock.Acquire(); // Get Lockwhile (queue.isEmpty()) { dataready.wait(&lock); // If nothing, sleep } item = queue.dequeue(); // Get next item lock.Release(); // Release Lock return(item); }
Short Answer • What is the difference between Mesa and Hoare scheduling for monitors? • For Mesa scheduling, the signaler keeps the lock and CPU, while the signaled thread is simply put on the ready queue and will run at a later time. Further, a programmer with Mesa scheduled monitors must recheck the condition after being awoken from a Wait() operation [ i.e. they need a while loop around the execution of Wait().
Short Answer • What is the difference between Mesa and Hoare scheduling for monitors? • For Hoare scheduling, the signaler gives the lock and CPU to the signaled thread which begins running until it releases the lock, at which point the signaler regains the lock and CPU. A programmer with Hoare scheduled monitors does not need to recheck the condition after being awoken, since they know that the code after the Wait() is executed immediately after the Signal()
Short Answer • Explain when using a spin-lock can be more efficient. • Answer: If the expected wait time of the lock is very short (such as because the lock is rarely contested or the critical sections are very short), then it is possible that a spin lock will waste many fewer cycles than putting threads to sleep/waking them up. The important issue is that the expected wait time must be less than the time to put a thread to sleep and wake it up.
Short Answer • Give two reasons why this is a bad implementation for a lock: lock.acquire() { disable interrupts; } lock.release() { enable interrupts; } • Answer: (1) It prevents hardware events from occurring during the critical section, (2) User programs cannot use this lock, (3) It doesn’t work for data shared between different processors.
Semaphore Implementation public P() { lock.Acquire(); while (value == 0) c.Wait(); value--; lock.Release(); }
Semaphore Implementation public V() { lock.Acquire(); value++; c.Signal(); lock.Release(); }