read(counter)
1
Copy the shared value into a private register.
Code
Bhavya
Learn why correct individual instructions can produce an incorrect shared result, then use atomic operations, mutexes, semaphores and monitors to control every permitted interleaving.
Two execution paths may each be locally valid while their combined read–modify–write operations create a result that depends on timing.
read(counter)
1
Copy the shared value into a private register.
add 1
2
Change the private copy.
write(counter)
3
Store the private value back into shared memory.
An unsafe interleaving lets both paths read the original value before either writes. Two writes then store the same incremented value, so one logical update disappears.
At most one process executes its critical section for the protected resource at a time.
Prevents simultaneous conflicting accessIf nobody is inside and some processes want to enter, the choice cannot be postponed indefinitely by unrelated processes.
Prevents needless standstillAfter requesting entry, a process has a finite bound on how often others may enter first.
Prevents starvationUse for small counters, flags or compare-and-swap loops when the invariant is compact.
Low overhead; reasoning can become subtleLock before a critical section and unlock afterward. Ownership makes it suitable for protecting a shared object.
Only the owner should unlockAn integer count coordinates a pool of identical resources or records available buffer slots.
wait consumes; signal returnsA 0/1 semaphore can provide exclusion or event ordering, but generally has no ownership rule.
More general than a mutexOnly one active execution enters the monitor at a time; condition variables express when operations may proceed.
Higher-level, structured safetyWait releases the associated lock and sleeps; after waking, the predicate must be checked again.
Always wait in a loop| Need | Good starting tool | Reason |
|---|---|---|
| Protect one shared data structure | Mutex | Clear ownership and one critical region |
| Limit access to N identical resources | Counting semaphore | The count represents available permits |
| Increment a simple independent counter | Atomic operation | Avoids a larger lock when the operation is truly atomic |
| Wait until a queue becomes non-empty | Condition variable + mutex | The condition is a predicate over protected state |
| Package shared state with safe operations | Monitor | Encapsulation reduces protocol mistakes |
Choose a semaphore type and request operations. The lab applies atomic wait and signal rules and exposes the queue state after every step.
Choose a process and execute wait(S).
The buffer has four slots. Produce and consume items while watching the three semaphore values and the required ordering.
Ready: empty = 4, full = 0, mutex = 1
Produce an item or try consuming from the empty buffer.
Protect the invariant, not unrelated computation or slow I/O.
When multiple locks are necessary, acquire them in a documented global order.
Structured cleanup must unlock after success, failure, cancellation or exception.
A wake-up means “check again,” not “the condition is guaranteed true.”
Block when the expected wait is longer than the cost of sleeping and waking.
Use tested libraries and message-passing designs instead of inventing lock protocols.
Peterson’s two-process algorithm uses intent flags and a turn variable to demonstrate mutual exclusion, progress and bounded waiting under its theoretical memory assumptions. It is important for learning correctness arguments. Modern compilers and processors reorder memory operations, so production code uses language/library synchronization primitives with defined memory-order guarantees.
Feedback explains the exact protocol or reasoning error.
Mark Level 6 after you can trace wait/signal and explain why producer–consumer needs all three semaphores.
Saved only in this browser.