Threads Memory Model
- Conceptual model
- Multiple threads run within the context of a single process
- Each thread has its own separate thread context
- Thread ID, stack, stack pointer, PC, condition codes, and GP registers
- All threads share the remaining process context
- Code, data, heap, and shared library segments of the process virtual address space
- Open files and installed handlers
- Operationally, this model is not strictly enforced
- Register values are truly separate and protected, but…
- Any thread can read and write the stack of any other thread
Mapping Variable Instances to Memory
- Global variables
- Variable declared outside of a function
- Virtual memory contains exactly one instance of any global variable
- Local variables
- Variable declared inside function without static attribute
- Each thread stack contains one instance of each local variable
- Local static variables
- Variable declared inside function with the static attribute
- Virtual memory contains exactly one instance of any local static variable
Concurrent Execution
- Key idea: In general, any sequentially consistent interleaving is possible, but some give an unexpected result
Enforcing Mutual Exclusion
- How to guarantee a safe trajectory
- Semaphores
- Mutex and condition variables
- Monitors
Semaphores
- non-negative global integer synchronization variable. Manipulated by P and V operations.
- P(s)
- If s is nonzero, then decrement s by 1 and return immediately
- Test and decrement operations occur atomically
- If s is zero, then suspend thread until s becomes nonzero and the thread is restarted by a V operation
- After restarting, the P operation decrements s and returns control to the caller
- If s is nonzero, then decrement s by 1 and return immediately
- V(s)
-
Increment s by 1
- Increment operation occurs atomically
-
If there are any threads blocked in a P operation waiting for s to become non-zero, then restart exactly one of those threads, which then complete operation by decrementing s
-
Using Semaphores for Mutual Exclusion
- Basic idea
- Associate a unique semaphore mutex, initially 1, with each shared variable (or related set of shared variables)
- Surround corresponding critical sections with P(mutex) and V(mutex) operations
- Terminology
- Binary semaphore: semaphore whose value is always 0 or 1
- Mutex: binary semaphore used for mutual exclusion
- P operation: "locking" the mutex
- V operation: "unlocking" or "releasing" the mutex
- "Holding" a mutex: locked and not yet unlocked
- Counting semaphore: used as a counter for set of available resources
Summary
- Programmers need a clear model for how variables are shared by threads
- Variables shared by multiple threads must be protected to ensure mutually exclusive access
- Semaphores are a fundamental mechanism for enforcing mutual exclusion