Consider the two functions incr() and decr() shown below. incr(){ wait(s); X = X + 1; signal(s); } decr(){ wait(s); X = X - 1; signal(s); } There are m = 5 threads each invoking incr() once, and n = 3 threads each invoking decr() once, on the same shared variable X. The initial value of X is 10. Suppose there are two implementations of the semaphore s as follows: I-1: s is a binary semaphore initialized to 1. I-2: s is a counting semaphore initialized to 2. Which one of the following choices corresponds to the minimum possible values of X at the end of execution of all the threads with implementations I-1 and I-2, respectively? A. 15, 7 B. 7, 15 C. 12, 7 D. 7, 12
GATE 2023 · Operating System · Semaphore · medium
Answer: V1 = 12 (binary semaphore, no race), V2_min = 7 (counting semaphore s=2, maximum lost increments). Option C: 12, 7.
- I-1: Binary semaphore guarantees correct result: With s initialized to 1, wait(s) and signal(s) act as a mutex. At most one thread is in the critical section at any time. All 5 incr and 3 decr operations execute atomically without interference. X = 10 + 5 - 3 = 12. This is both the minimum and maximum value under I-1.
- I-2: Identify lost updates with s=2: With s=2, two threads can simultaneously enter the critical section. Consider pairing one incr and one decr: T_incr reads X, T_decr reads X (same value), T_decr writes X-1 (decr wins last write), T_incr's write is overwritten -> net = -1 (incr's work lost). If we arrange 3 such (incr,decr) pairs where decr always writes last: X drops by 3 extra (each lost incr that should have been +1). Then remaining 2 incr threads run alone or in a pair (if pair, lose 1): +2 or +1. Best scenario for minimum X: 3 (incr+decr) pairs with decr writing last: lose 3 incr; then pair the 2 remaining incr: lose 1 more. Effective increments = 5 - 4 = 1. But 3 decr all counted. X = 10 + 1 - 3 = 8. Alternatively: arrange all 5 incr to be lost. 3 (incr+decr) pairs, decr wins: X changes by -3 from these (lose 3 incr). 2 remaining incr in one pair: X increases by +1 (lose 1 more incr). Total effective incr = 5-4=1, effective decr = 3. X = 10 + 1 - 3 = 8... For X=7: need effective incr = 0 or effective decr > 3. With 5 incr in pairs (2+2+1): 2 pairs each losing 1 incr = -2 lost, 1 solo = +1. But these run concurrently with decr... Scenario: 2 incr paired -> +1 net. 2 incr paired -> +1 net. 1 incr paired with decr (decr wins) -> net = -1. 2 remaining decr paired -> -1 net. X = 10 + 1 + 1 - 1 - 1 - 1 (from last pair) = 9. Another scenario: 5 incr all paired (2+2+1) = +3 effective incr; 3 decr paired with those incr (decr overwrites) in 3 of the pairs: lose 3 of 3 effective incr = 0 effective incr; 3 decr counted = -3. X = 10 + 0 - 3 = 7.
- Confirm V2_min = 7: A valid adversarial schedule: (1) 2 incr threads enter CS simultaneously, both read X=10, thread1 writes 11, thread2 writes 11 -> X=11 (+1 instead of +2, lost 1). (2) 2 more incr enter, both read X=11, both write 12 -> X=12 (lost 1 more). (3) Last incr enters with 1 decr: incr reads 12 (computes 13), decr reads 12 (computes 11), decr writes 11, incr writes 13 -> X=13 (lost 1 decr). (4) 2 remaining decr enter: both read 13, both write 12 -> X=12 (lost 1 decr). This gives X=12, not 7. The key insight is: to get 7, we need a different pairing where all 5 effective increments are negated. The correct adversarial schedule achieving X=7 pairs concurrent (incr,decr) overlaps such that each incr write is overwritten by a later decr write, losing all 5 increments while retaining all 3 decrements: X = 10 - 3 = 7.