Goal for multiple node concurrency is to mitigate one node's failure
Critical Section: piece of code accessing a shared resource, usually variables or data structures
Race Condition: Multiple threads of execution enter CS at the same time, update shared resource, leading to undesirable outcome
Indeterminate Program: One or more Race Conditions, output of program depending on ordering, non deterministic
Mutual Exclusion: guarantee that only a single thread/process enters a CS, avoiding races
Correctness: single process at critical section
Efficiency: no spin-locks
Fairness: no process wait for ever
Mutual Exclusion: Atomic setting and testing implemented by hardware.
Semaphores: shared address space with integer variable with increase
and decrease
operations.
Note that binary semaphores is logically identical with mutex.
Condition Variables (cvars): thread suspended until activated by other threads (more efficient than spin lock)
cvar.Wait():
Must be called after locking mutex.
Atomically: release mutex & suspend operation
When resume, lock mutex (but maybe not right away)
cvar.Signal():
If no thread suspended, then NO-OP
Wake up (at least) one suspended thread.
(Typically do within scope of mutex, but not required)
Resume isn't safe since it may not lock mutex right away... so you end up with a while
loop to recheck condition.
There are channel
s and goroutine
s.
channel: communicate between goroutine
goroutine: independently execute functions (independent call stack, but inexpensive)
The idea is instead of communicating with shared memory, we simulate shared memory by communication.
When channel capacity is 0, it becomes a synchronization point. You can only send to a chanel of capacity 0 if and only if there exist processes currently listening.
Note that if you are running in one core, 0 capacity channel might have logical deadlock, but I believe golang will work it out.
Note that there isn't really reason to use channel size other than 0 or 1. Big channel size might hide concurrency bugs.
You can use channels to implement mutex.
Limitation to channels:
bounded channel size buffer
no way to test for emptiness
you cannot put back values to head of channel
cannot flush channel
cannot peak channel
Q: How do you change a lightbulb in concurrent programming?
A. You take the lamp to a secure area so nobody else can try to change the lightbulb while you're changing it. Alternatively, you might get a lamp with lightbulbs that can't be changed, and just get a new lamp when the lightbulb goes out.
Table of Content