## Race Conditions
### Definition - Two or more processes are reading or writing some shared data and the final result depends on who runs precisely when.
### Tanenbaum example (Printer daemon) - Process enters name of file in spooler dir - Printer daemon checks to see if file need printing - Prints and removes names from spooler dir - Spooler dir has 0 ... infinity - Two shared variables, output, point at file to be printed - in, points to free slot in spooler dir - Proc A and B queue file for printing - A reads in, stores slot 7 in variable - Clock interrupt occurs - B reads in, stores slot 7 in same variable - B writes to slot 7, updates in to slot 8 - A writes to slot 7, erasing what B put there, updates in to slot 8 - Spooler dir now in sync - B never receives output
### Golang example (Incrementing a counter) - Proc 1 read counter 0 - Yield thread 0 - Increment counter 1 - Proc 2 read counter 0 - Yield thread 0 - Increment counter 1 - Proc 1 write counter 1 - Proc 2 write counter 1 - Proc 1 read counter 1 - Yield thread 1 - Increment counter 2 - Proc 2 read counter 1 - Yield thread 1 - Increment counter 2
### Go-isms - go run -race main.go - Don't communicate by sharing memory, share memory by communicating - Passing on a channel the data structure or object.
### Avoiding Race Conditions - No two processes may be simultaneously inside their critical regions. - No assumptions may be made about speeds or the number of CPUs. - No process running outside its critical region may block any process. - No process should have to wait forever to enter its critical region.
### Mutal Exclusion - While a process is busy updating shared memory no other process will attempt to enter shared memory space. - Disabling interrupts (Single CPU) - This approach is generally unattractive because it is unwise to give user processes the power to turn off interrupts. - Lock variables - Test the lock - If 0 set to 1 - Before process can set 0 to 1, another process reads as 0 - The race now occurs if the second process modifies the lock just after the first process has finished its second check. - Busy Waiting - It should usually be avoided, since it wastes CPU time - Mutual Exclusion Algorithm: G. L. Peterson - Each process calls enter\_region - Wait, if necessary, until safe to enter shared memory region - Process calls leave\_region after done with shared memory
``` #define FALSE 0 #define TRUE 1 #define N 2 / * number of processes * / int turn; / * whose turn is it? * / int interested[N]; / * all values initially 0 (FALSE) * /
void enter region(int process); / * process is 0 or 1 * / {
int other; / * number of the other process * /
other = 1 − process; / * the opposite of process * / interested[process] = TRUE; / * show that you are interested * / turn = process; / * set flag * / while (turn == process && interested[other] == TRUE) / * null statement * / ; }
void leave region(int process) / * process: who is leaving * / { interested[process] = FALSE; / * indicate departure from critical region * / } ```
Podchaser is the ultimate destination for podcast data, search, and discovery. Learn More