Java Concurrent
Introduction
Thread’s advantage
- unleash the performance of processor
- simplification of modeling
- simplified handling of asynchronous events
- responsive user interface
Thread’s disadvantage
- security problems
- activation problems
- performance problems
Thread Safety
keyword synchronized volatile
solve problems of multiple threads access mutable variables:
- don’t share the variable in threads
- change the variable to immutable
- use sync when access variables
Thead Safety: When multiple threads access a class, no longer the running environment uses any scheduling methods or the threads alternately execute, and the main code needn’t any other sync or synergy, the class can perform rightly.
Sateless object is thread safe.
Atomic
Race condition: Check-Then-Act.
Lock
Built-in lock: synchronized. equivalent to a mutual exclusion lock. can re-entry.
Sharing of Object
Visibility
use volatile
don’t let this escape when construct.
Thread Closure
Ad-hoc thread closure.
Stack closure.
ThreadLocal
Immutability
Immutable object must be thread safe.
Composition of Object
- find all variables constructing the object status
- find the immutable condition binging status variables
- build concurrent manage strategies of object status
Basic Building Blocks
- Sync container class (Vector and Hashtable)
- Concurrent container class (ConcurrentHashMap CopyOnWriteArrayList)
- Blocking queue ans Producer and Customer
- Blocked method and Interrupted method
- Sync util class
Task execution
Execute task in thread
Serial execution, create explicitly thread for task.
Disadvantage of infinite threads
- Thread lifecycle overhead high
- resource consumption
- stability
Executor framework
public interface Executor {
void execute(Runnable command)
}
Thread pool: use static methods in class Executor
newFixedThreadPool
create a fixed length poolnewCachedThreadPool
create a pool can cachenewSingleThreadExecutor
create a single thread executornewScheduledThreadPool
schedule tasks
use shutdown()
in interface ExecutorService extents Executor
to shutdown an executor.
Executor has three status in lifecycle,running, closed, terminated.
Find available concurrent
Callback and Future
CompletionService
include Executor
and BlockingQueue
. use blocked method take
and poll
get result.
Cancel and Close
Java doesn’t apply any mechanisms to stop thread safely. And should avoid using Thread.stop
ro suspend
.
Task cancel
cancel reasons:
- user request cancel
- operation with time limit
- application event
- error
- close
interrupt methods:
- response interrupt (wait, sleep)
- use Future implement cancel
Calling interrupt
doesn’t mean the thread stops its work immediately, rather than send a message of requesting interrupt.
Usually interrupt is the best method to implement cancel.z
uninterrupted block
- Java.io sync Socket I/O
- Java.io sync I/O
- Selector async I/O
- get some lock
package standard cancel operation to process uninterrupted block.
use newTaskFor
to package substandard cancel
Stop service based on thread
For the service holding threads, as long as the service’s existing time is longer than the threads’, the service should apply lifecycle methods.
Thread Pool
Implicit Coupling between Tasks and Execution Strategies
tasks need specified execution strategies
- dependent tasks
- tasks using thread closure
- time sensitive tasks
Thread pool problems:
- Deadlock
- long-time tasks
Set Thread Pool size
W/C = ratio of wait time to compute time
N(threads) = N(cpu) * U(cpu) * (1 + W / C)
int N_CPUs = Runtime.getRuntime().availableProcessors();
Configure ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
int corePoolSize
basic size
BlockingQueue workQueue
has three basic kinds
- boundless queue: boundless
LinkedBlockingQueue
innewFixedThreadPool
andnewSingleThreadExecutor
- bounded queue:
ArrayBlockingQueue
, boundedLinkedBlockingQueue
,PriorityBlockingQueue
SynchronousQueue
only in boundless thread pool or rejected pool.
RejectedExecutionHandler handler
when queue is filled up, saturation strategy takes effect.
Abort
default strategy. throwRejectedExecutionException
Discard
discard this taskDiscard-Oldest
discard next task, and submit this task againCaller-Runs
run task in this thread
ThreadFactory threadFactory
custom threads
Expand ThreadPoolExecutor
BeforeExecute
afterExecute
terminated
Concurrent Recursion
DFS
GUI Application
separate threads for GUI and task.
Avoid Active Hazards
Deadlock
- lock sequence deadlock: change to the same sequence
- dynamic lock sequence deadlock: use some methods like hash to control lock sequence.
- deadlock between collaborating objects: open call, only protect code blocks about concurrent.
avoid deadlock:
- use time lock
- use Thread Dump to analyze
Other Hazards
- Starvation
- Terrible Responsiveness
- LiveLock
Performance and Scalability
Thread overhead
- context switch
- memory sync
- block
Reduce Lock Competition
- reduce lock’s scope
- reduce lock’s granularity
- lock segment
- avoid hot spot area
- give up exclusive lock
- monitor CPU usage
- don’t use object pool
- reduce context switch’s overhead
Explicit Lock
ReentrantLock
ReentrantLock
implement Lock
interface, and apply the same mutual exclusivity and memory visibility as synchronized
choose between synchronized
and ReentrantLock
: Choose ReentrantLock
when need some advanced functions include timed, pollable, interruptible, fair queue, and non-block structure.
Read-Write Lock
ReadWriteLock
Custom Sync Tool
Condition Queue
wait()
notify()
notifyAll()
a queue of threads wait for some specified conditions to be true.
usually use notifyAll()
, use notify()
when:
- all threads use the same condition
- single in and out
Explicit Condition Object
Like ReentrantLock
with Lock
, Condition
is kind of general condition queue.
Synchronizer
ReentrantLock
and Semaphore
use AbstractQueuedSynchronized
to implement fair and unfair lock.
AQS
TODO
Atomic Variable and non-block sync
Disadvantages of Lock
schedule overhead
Hardware’s support for Concurrent
CAS
When many threads try use CAS change a variable, only one can success.
Atomic Variable Class
Atomic Variable
is a kind of gooder volatile
Non-Block Algorithms
Treiber Algorithms
Michael-Scott Algorithms
ABA problem: when use CAS, variable change from A to, and form B to A.
solve: use AtomicStampedReference
or AtomicMarkableReference
Java Memory Model
from Deeper Understanding JVM
Happens-Before
- Program Order Rule
- Monitor Loc Rule
- Volatile Variable Rule
- Thread Start Rule
- Thread Termination Rule
- Thread Interruption Rule
- Finalizer Rule
- Transitivity