Today
-
Critical sections
-
Spinlocks
-
Locks
ASST1 Checkpoint
-
If you have not started, you’re way behind.
-
If you don’t understand semaphores, you’re way behind.
-
If you only have working locks, you’re behind.
-
If you have working CVs, you’re behind.
-
If you have solved only one of the synchronization problems or have working reader-writer locks, you’re a bit behind.
-
If you’ve solved two, you’re OK.
-
Keep in mind: you need working locks and CVs for future assignments.
-
(The rest of the assignment is for points and won’t hurt you as much in the future.)
-
Fast Forward: Synchronization
-
The OS creates the illusion of concurrency by quickly switching the processor(s) between multiple threads
-
We will back up and discuss how this happens after discussion synchronization
-
-
Threads are used to abstract and multiplex the CPU
Pandora’s Concurrency Box
-
It helps us think about how to structure our applications.
-
It hides latencies caused by slow hardware devices.
-
Coordination: how do we enable efficient communication between the multiple threads involved in performing a single task?
-
Correctness: how do we ensure that shared state remains consistent when being accessed by multiple threads concurrently? How do we enforce time-based semantics?
-
We will focus on correctness today but return to coordination later.
Patient 0
-
It is multiplexing access to hardware resources and therefore sharing a great deal of state between multiple processes!
-
It frequently uses many threads to hide hardware delays while servicing devices and application requests.
-
Lots of shared state plus lots of threads equals a difficult synchronization problem.
-
Also, if the operating system gets synchronization wrong bad things happen.
Concurrency v. Parallelism
The Go developers have a great description of this distinction. According to them:
…when people hear the word concurrency they often think of parallelism, a related but quite distinct concept. In programming, concurrency is the composition of independently executing processes, while parallelism is the simultaneous execution of (possibly related) computations. Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.
Watch the video to find out more.
Unless Shown Otherwise…
Concurrency forces us to relax any assumptions that we may want to make about how any particular thread executes.
-
Be run in any order,
-
Be stopped and restarted at any time,
-
Remain stopped for arbitrary lengths of time.
-
Generally these are good things—the operating system is making choices about how to allocate resources.
-
When accessing shared data these are challenges that force us to program more carefully.
The Bank Example
Consider the following code snippet.
void giveGWATheMoolah(account_t account, int largeAmount) {
int gwaHas = get_balance(account);
gwaHas = gwaHas + largeAmount;
put_balance(account, gwaHas);
notifyGWAThatHeIsRich(gwaHas);
return;
}
-
One of you is depositing $1,000 (this person gets a B).
-
One of you is depositing $2,000 (A- material).
Things Go Well
A- Student | B Student | Balance |
---|---|---|
|
|
$1000 |
|
|
$3000 |
|
|
$4000 |
Things Go Less Well
A- Student | B Student | Balance |
---|---|---|
|
|
$1000 |
|
|
|
|
|
|
|
|
$2000 |
|
|
$3000 |
Things Go Very Badly
A- Student | B Student | Balance |
---|---|---|
|
|
$1000 |
|
|
|
|
|
|
|
|
$3000 |
|
|
$2000 |
Race Conditions
A race condition is "when the output of a process is unexpectedly dependent on timing or other events."
-
We expected me to have $4,000 after both deposits. (Otherwise we are not observing the Law of the Conversation of Money, probably important to banks except during bailouts.)
Concurrency v. Atomicity
-
Requires stopping or starting any thread at any time.
-
Requires not stopping certain threads at certain times or not starting certain threads at certain times, i.e. providing some limited control to threads over their scheduling.
Critical Sections
-
This set (or sets) of instructions will look atomic with respect to other threads executing code within the critical section.
Critical Sections
void giveGWATheMoolah(account_t account, int largeAmount) {
int gwaHas = get_balance(account);
gwaHas = gwaHas + largeAmount;
put_balance(account, gwaHas);
notifyGWAThatHeIsRich(gwaHas);
return;
}
-
What is local state private to each thread? gwaHas
-
What is the shared state that is being accessed by giveGWATheMoolah? account
-
What lines are in the critical section? 2-4
Critical Section Requirements
-
Mutual Exclusion: this is the most basic property. Only one thread should be executing in the critical section at one time.
-
Progress: all threads should eventually be able to proceed through the critical section.
-
Performance: we want to keep critical sections as small as possible without sacrificing correctness.
Next Time
-
Sleep and spin locks
-
Problems with Synchronization Primitives
-
Solving Sample Synchronization Problems