Decomposing a Problem: Critical Section and Synchronization Techniques in CS - Prof. B. Ke, Study notes of Operating Systems

The critical section problem in computer science and various synchronization techniques such as test and set, semaphore, and interrupts to ensure mutual exclusion and prevent data inconsistency. Different versions of using shared global variables, un-interruptable test & set, and semaphores. It also discusses the producer/consumer problem and readers-writers problem as classical synchronization problems.

Typology: Study notes

Pre 2010

Uploaded on 02/13/2009

koofers-user-bho-1
koofers-user-bho-1 🇺🇸

10 documents

1 / 44

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Chapter 8
Basic Synchronization Principles
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c

Partial preview of the text

Download Decomposing a Problem: Critical Section and Synchronization Techniques in CS - Prof. B. Ke and more Study notes Operating Systems in PDF only on Docsity!

Chapter 8

Basic Synchronization Principles

? Multiprogramming

? Multiple concurrent, independent processes

? Those processes might want to coordinate activities

? Clearly, synchronization is needed if

? A wants B to read x after it writes it & before it re-writes

Proc A {

while (true) {

write(x)

read(y)

Proc B {

while (true) {

read(x)

write(y)

Need for Synchronization

shared x, y

Critical Section Problem

/* Code schema for p1 */

..

balance = balance + amount;

..

/* Code schema for p2 */ .. balance = balance - amount; ..

/* Schema for p1 / / X == balance */ load R1, X load R2, Y add R1, R store R1, X

/* Schema for p2 / / X == balance */ load R1, X load R2, Y sub R1, R store R1, X

shared float balance;

Critical Section Problem…

? Suppose:

? Execution sequence : 1, 2, 3

? Lost update : 2

? Execution sequence : 1, 4, 3 ,

? Lost update : 3

? Together => non-determinacy

? Race condition exists

/* Schema for p1 */ load R1, X load R2, Y add R1, R store R1, X

/* Schema for p2 */ load R1, X load R2, Y sub R1, R store R1, X

Using Shared Global Variables – Ver 2

procedure processone; begin while true do begin while p2inside do ; p1inside := true; criticalsectionone; p1inside := false; otherstuffone; end end

procedure processtwo; begin while true do begin while p1inside do ; p2inside := true; criticalsectiontwo; p2inside := false; otherstufftwo; end end

  • Process 1 & 2 can both be in the critical sections at the same time

Because Test & Set operations are not atomic

==> Move setting of p1inside/p2inside before test

Shared boolean: p1inside <= false, p2inside <= false;

Using Shared Global Variables – Ver 3

procedure processone; begin while true do begin p1wantsin := true; while p2wantsin do ; criticalsectionone; p1wantsin := false; otherstuffone; end end

procedure processtwo; begin while true do begin p2wantsin := true; while p1wantsin do ; criticalsectiontwo; p2wantsin := false; otherstufftwo; end end

  • Deadlock can occur if both sets flag at the same time

==> Need a way to break out of loops…..

Shared boolean: p1wantsin <= false, p2wantsin <= false;

Using Interrupts…

? This works BUT …

? Allows process to disable interrupts for arbitrarily long time

? What if I/O interrupt needed?

? What if one of the processes is in infinite loop inside the

Critical Section

? Let’s examine the use of Shared Variables again….

Using Shared Variable to Synchronize

/ Program for P1 / .. /* Acquire lock / while(lock) {NULL;}; lock = TRUE; / Execute critical section / balance = balance + amount; / Release lock */ lock = FALSE; ..

/ Program for P2 / .. /* Acquire lock / while(lock) {NULL;}; lock = TRUE; / Execute critical section / balance = balance - amount; / Release lock */ lock = FALSE; ..

shared boolean lock <= FALSE; shared float balance;

lock == FALSE

=> No process in CS

=> Any process can enter CS

lock == TRUE

=> One process in CS

=> No other process admitted to CS

Un-interruptable Test & Set

enter( lock ) {

disableInterrupts(); /* Loop until lock TRUE / while (lock) { / Let interrupts occur */ enableInterrupts(); disableInterrupts(); } lock = TRUE; enableInterrupts();

}

exit( lock ) { disableInterrupts(); lock = FALSE; enableInterrupts(); }

Enable interrupts so that the OS, I/O can use them

Re-disable interrupts when ready to test again

Un-interruptable Test & Set…

? Note

? CS is totally bounded by enter/exit

? P2 can still wait (waisted CPU cycles) if P1 is interupted after

setting lock (i.e., entering critical section), but

? Mutual exclusion is achieved!!!!!

? Does not generalize to multi-processing

P

enter(lock); balance = balance + amount; exit(lock);

P

enter(lock); balance = balance - amount; exit(lock);

CS^ CS

? Solution

/ Program for P1 / enter(listLK); < delete element >; exit(listLK); ; enter(lngthLK); < update length >; exit(lngthLK);

Suppose: P1... ; P2 runs & finishes; P1 …….

Any access to lngth vble during “intermediate comp.”will be incorrect !!!

=> Programming Error: List and variable need to be updated together

Protecting Multiple Components: 1st^ try

Shared: list L,

boolean ListLK <= False;

boolean LngthLK <= False;

/ Program for P2 / enter(lngthLK); < update length >; exit(lngthLK); ; enter(listLK); < delete element >; exit(listLK);

? Suppose: P1... ;

P2 runs to? and blocks ;

P1 starts & blocks on “enter”

=> DEADLOCK

/ Program for P1 / enter(listLK); < delete element >; ; enter(lngthLK); < update length >; exit(listLK); exit(lngthLK);

Protecting Multiple Components: 2nd^ try

Shared: list L,

boolean ListLK <= False;

boolean LngthLK <= False;

/ Program for P2 / enter(lngthLK); < update length >; ; enter(listLK) < delete element >; exit(lngthLK); exit(listLK);

CS 1
CS 2
CS 2
CS 1

Solution to Synchronization

? The previous examples have illustrated 2 methods for

synchronizing / coordinating processes

? Interrupt

? Shared variable

? Each has its own set of problems

? Interrupt

? May be disabled for too long

? Shared variable

? Test, then set – interruptable

? Non-interruptable – gets complex

? Dijkstra introduces a 3rd^ and much more preferable

method

? Semaphore

Semaphore

? Dijkstra, 1965

? Synchronization primitive with no busy waiting

? It is an integer variable changed or tested by one of

the two indivisible operations

? Actually implemented as a protected variable type

var x : semaphore