Professor:
- Paulo Pereira, office F.0.21
Schedule:
- Tuesday, 14:00-15:30, G.0.13 (LS1)
- Friday, 14:00-17:00, G.0.20 (LS5)
Moodle
- Threading on the JVM
- Motivations
- Core execution model
- Creating threads: the
Threadclass - Thread states and lifecycle (initial version)
- NEW, RUNNABLE (Running vs Ready), TIMED_WAITING, TERMINATED
- Implications of the execution model
- Non-determinism
- Interleaving of thread execution
- For reference:
- Review
- Week 1 recap
- Lab 1 Exercise 5 solution discussion (our first concurrent echo server)
- Orchestrating thread execution
- Thread coordination and synchronization
- Synchronization by completion:
join()and theWAITINGstate
- Computing with threads:
- Memory areas revisited: global (statics), heap and stack (thread-confined vs shared data)
- Data parallelism (i.e. fork–join pattern, or embarrassingly-parallel + reduce)
- Speedup limits: Amdahl's law
- Deterministic outcomes despite non-deterministic scheduling (isolate + join + reduce)
- Compute bound vs I/O bound tasks
- Discussion of the limitations of the "one thread per client" approach for our echo server
- For reference:
- Thread safety
- What thread safety means
- Correctness goals under concurrent execution
- Approaches to thread safety
- Immutability (no mutations)
- Thread confinement (no sharing)
- Mutual exclusion (shared mutable state with synchronization)
- Protecting compound actions over shared state
- Mutual exclusion and invariants
- Explicit locks with
ReentrantLock(main focus) - Intrinsic locks with
synchronized(brief coverage)
- Thread-safety hazards (race conditions)
- Compound actions on shared mutable state
- Read-modify-write
- Check-and-act
- Lost updates
- Examples: loss of increments, loss of list insertions
- Compound actions on shared mutable state
- For reference:
- Part 1: Threading on the JVM: synchronization
- Synchronization on the JVM
- Data synchronization
- Control synchronization
- Control synchronization: synchronizers
- Purpose and motivation
- Example 1:
ValueHolder
- Synchronization on the JVM
- Part 2: Threading on the JVM: monitors
- Building custom synchronizers using Lampson and Redell monitors
- Purpose and motivation
- Lampson and Redell semantics
- Guarded blocks and condition predicates
- Demo: Implementing a
Latchsynchronizer (without support for timeout or cancelation)
- Building custom synchronizers using Lampson and Redell monitors
- For reference:
- Building custom synchronizers using Lampson and Redell monitors, continued
- Review: Recap of the simple
ValueHoldersynchronizer from last week
- Review: Recap of the simple
-
The Delegated Execution pattern (a.k.a. kernel style approach)
-
Demos:
- producer-consumer with
UnboundedBuffer,UnboundedQueueandBlockingQueue(discussion of variants and the importance of bounded capacity to achieve back-pressure) ManualResetEventto illustrate another variant of the same pattern with space optimizations- No support for timeout or cancelation this week. That is a subject for next week
- producer-consumer with
-
For reference:
- Building custom synchronizers using Lampson and Redell monitors, continued
- Review: Recap of the Delegated Execution pattern (a.k.a. kernel style approach)
- Monitor based solutions
- Why timeout and cancelation support matter
- Correct timeout handling
- Absolute deadline vs relative timeout
- Recompute remaining time after each wake-up
- Correct cancelation handling
- Interrupt protocol
- Cancelation of pending requests and state cleanup
- Avoiding leaks/stale waiters in request lists
- Demos:
BlockingQueuewith support no support for cancelation or timeout and with no optimizationsUnboundedQueuewith support for cancelation and timeout with no optimizationsUnboundedQueuewith support for cancelation and timeout
- Validation strategy
- Functional tests for success/timeout/cancelation paths
- Stress tests for races between signal, timeout, and cancelation
- For reference:
- Part 1: Optimization of monitor-based synchronizers
- Review: timeout and cancelation support on monitor-based solutions
- Demo: Implementing a custom thread pool
- Part 2: Thread pools
- Purpose and motivation
- Fixed-size worker pools and work queues
- Back-pressure and bounded queues, revisited
- Compute-bound vs I/O-bound sizing considerations
- For reference:
- Structured concurrency in Kotlin
- Motivation and goals
- Coroutines and suspending functions
- Coroutines as sequences of continuations
- Continuation-passing style (CPS)
- Suspension points and resumption
- Demos:
- Hello Coroutines - launching coroutines using
launchinside arunBlockingscope - Hello Continuations - manual CPS transformation and execution using
startCoroutine,suspendCoroutineand theContinuationinterface
- Hello Coroutines - launching coroutines using
- For reference:
- Coroutines as sequences of continuations
- Continuation-passing style (CPS)
- Suspension points and resumption
- Cooperative scheduling and yielding
- Demos:
- Let's yield - Implementing our homemade
yieldfunction to illustrate the concept of suspension and resumption while scheduling continuations on the same thread (first in the main thread and then on a single-threaded executor) - Let's delay - Implementing our homemade
delayfunction to illustrate the concept of suspension and resumption while scheduling continuations on ScheduledExecutorService (first with a single-threaded scheduled executor and then with a multithreaded one to illustrate the non-determinism of resumption when multiple continuations are scheduled for the same time)
- Let's yield - Implementing our homemade
- For reference:
- Lecture video (coming soon)
- Assignment 2