Java Concurrency - Part 1: Introduction
3 min readFeb 10, 2021
This article is a part of the Java Programming Language article series.
Concurrency
- Performing multiple actions at the same time
- Listening to music, watching movies: streaming audio and video, listening and watching
- Browsing websites while downloading files in the web browser
- Processing time for a single core is shared among processes and threads through an OS feature called time slicing
Process
- A runtime environment with its own memory space
- An application can consist of one or more processes
- Inter Process Communication (IPC) resources are used to facilitate communication between processes in operating systems
- IPC provides communication on the same computer or between different computers
- Socket programming
Thread
- Lightweight processes
- Each process has at least one thread
- Threads share the resources of the process
- System threads: memory management, signal handling
- Program startup thread: main thread
- Run asynchronous tasks
- Priority can be assigned to threads
- Thread class
Thread Class Methods
- start(): Starts the thread
- Thread.sleep(): Pauses execution
- interrupt(): Stops the thread
- Thread.interrupted(): Checks if thread is interrupted, throw an InterruptedException
- join(): Allows one thread to wait for the completion of another, dependent on the OS for timing
- isAlive(): Checks if thead is alive
- Thread.currentThread().getName(): Gets current thread name
Using Thread Class
Option 1: Implement Runnable interface
Option 2: Extend Thread class
Synchronization
- Threads communicate by sharing access to fields
- Errors: Thread Interference, Memory Consistency Errors
- Solution: Synchronization
Causes
- Thread contention: Starvation and livelock
- Two or more threads try to access the same resource simultaneously
- One or more threads are executed more slowly or suspended
Use
- Synchronized Methods
- Synchronized Statements
- Implicit Locks and Synchronization
- Atomic Access
Thread Interference
- Acting on the same data with multiple operations running in different threads
c++ expression
- Retrieve the current value of c
- Increment the retrieved value by 1
- Store the incremented value back in c
Case
- Thread A invokes increment
- Thread B invokes decrement
- The initial value of c is 0
Possibility 1
- Thread A: Retrieve c
- Thread B: Retrieve c
- Thread A: Increment retrieved value; result is 1
- Thread B: Decrement retrieved value; result is -1
- Thread A: Store result in c; c is now 1
- Thread B: Store result in c; c is now -1
Thread interference bugs can be difficult to detect and fix
Memory Consistency Errors
- Inconsistent views of the same data with different threads
Case
- Thread A increments counter
- Thread B prints out counter
Possibility 1
- The value printed out might well be 0
Solution
- The happens-before relationship: guarantees memory writes between different threads
Synchronized Methods
- Constructors cannot be synchronized
- Using the synchronized keyword with a constructor is a syntax error
- Causes liveness problems
Synchronized Statements
- Specify the object that provides the lock
Atomic Action
- Happens all at once
- Cannot stop in the middle
- No side effects are visible until it is complete
Atomic Access
- Reads and writes are atomic for reference variables and primitive variables (except long and double)
- Declare volatile: all variables
Liveness
- Ability to execute in a timely manner
Liveness Problems
- Deadlock
- Starvation
- Livelock
Deadlock
- A situation where two or more threads are blocked forever, waiting for each other
- Both threads will block when they attempt to invoke bowBack
- Neither block will ever end, because each thread is waiting for the other to exit bow
Starvation
- A situation where a thread is unable to gain regular access to shared resources and is unable to make progress
Case
- An object provides a synchronized method that often takes a long time to return
- If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked
Livelock
- A thread often acts in response to the action of another thread
- If the other thread’s action is also a response to the action of another thread, then livelock may result
Case
- Two people attempting to pass each other in a corridor