Concurrent Programming in Java Design Principles A
Concurrent Programming in Java Design Principles A
net/publication/220695832
CITATIONS READS
423 15,717
1 author:
Doug Lea
State University of New York at Oswego
105 PUBLICATIONS 2,859 CITATIONS
SEE PROFILE
All content following this page was uploaded by Doug Lea on 06 September 2014.
Doug Lea
C o n c u r r e n t
http://gee.cs.oswego.edu
1
Topics
Concurrency
J a v a
Libraries
http://gee.cs.oswego.edu/dl/cpj
The printed slides contain much more material than can be covered
in a tutorial. They include extra backgound, examples, and
C o n c u r r e n t
Java code examples often omit qualifiers, imports, etc for space
reasons. Full versions of most examples are available from the
CPJ online supplement.
Availability
Minimize response lag, maximize throughput
i n
Modelling
P r o g r a m m i n g
GUIs
i n
P r o g r a m m i n g
Server Daemons
C o n c u r r e n t
Simulations
Common examples
resources.
Common features
• Classes, state, references, methods, identity, constraints
i n
• Encapsulation
P r o g r a m m i n g
• Send a message
• Create a new object
Models differ in rules for these operations. Two main categories:
• Active vs Passive
• Concurrent models include features of both
• Lead to uniquely concurrent OO design patterns
8
Active Object Models
J a v a
state, acquaintances
message anAction {
i n
trigger
update state
oneway
P r o g r a m m i n g
send a message
make an object
}
main
P r o g r a m m i n g
trigger I/O
interpret() {
Program ...
}
a passive object
C o n c u r r e n t
objects participating
• Require scheduling in in other threads
order to coexist
• Initiate and control
new threads
11
Hardware Mappings
remote messages remote messages
memory cells
J a v a
state of
an object
CPU CPU
i n
P r o g r a m m i n g
Cache Cache
state of an object
Concurrency
• Thread-objects interpret passive objects
Networking and Distribution
• Server-objects pass around resources
C o n c u r r e n t
Objects
• ADTs, aggregate components, JavaBeans, monitors,
business objects, remote RMI objects, subsystems, ...
• May be grouped according to structure, role, ...
C o n c u r r e n t
method1
legal
temp
i n
method2 transient
P r o g r a m m i n g
states
method3 ??
legal temp
method4
C o n c u r r e n t
Related to efficiency
• Every called method should execute as soon as possible
C o n c u r r e n t
Safety-first Liveness-first
i n
20
Guaranteeing Liveness
“Something eventually happens”
J a v a
Availability
• Avoiding unnecessary blocking
i n
Progress
P r o g r a m m i n g
Citizenship
• Minimizing computational demands of sets of activities
Protection
• Avoiding contention with other programs
• Preventing denial of service attacks
• Preventing stoppage by external agents
21
Concurrency and Efficiency
Concurrency can be expensive
J a v a
Computation
• Construction, finalization overhead for resources
• Synchronization, context switching, scheduling overhead
Communication
C o n c u r r e n t
— “Inheritance anomalies”
Combat complexity
C o n c u r r e n t
• Static typing
P r o g r a m m i n g
• C-based syntax
— Garbage collection
}
}
P r o g r a m m i n g
}
public void run() {
for(;;) {
moveRandomly();
canvas.repaint();
try { Thread.sleep((int)(Math.random()*10);}
catch (InterruptedException e) { return; }
}
}
}
30
Java Concurrency Support
Thread class represents state of an independent activity
J a v a
Principal methods
P r o g r a m m i n g
Immutability
P r o g r a m m i n g
Locking
State dependence
C o n c u r r e n t
Containment
Splitting
Applications
➔ No storage conflicts
• No representational invariants
➔ No invariant failures
C o n c u r r e n t
➔ No liveness problems
ImmutableAdder(int x) { offset_ = x; }
i n
• java.lang.String
• java.lang.Integer
• java.awt.Color
class Relay {
private final Server delegate;
Relay(Server s) { delegate = s; }
i n
37
Locking
client
J a v a
internal state
lock
action { ... }
i n
host
client
P r o g r a m m i n g
class Location {
Location(double x, double y) { x_ = x; y_ = y; }
double y() {
synchronized (this) {
return y_;
C o n c u r r e n t
}
}
• Scalars like int are not Objects so can only be locked via
P r o g r a m m i n g
return n;
P r o g r a m m i n g
}
}
read 1
write 2
read 2 read 2
write 3
return 3
write 3
return 3
memory cells
CPU CPU
Cache Cache
unlock lock
state of object
C o n c u r r e n t
Constraints
• All methods must be synchronized: Java unsynchronized
methods execute even when lock held.
• No public variables or other encapsulation violations
• Methods must not suspend or infinitely loop
• Re-establish consistent state after exceptions
44
Deadlock
class Cell {
private long value_;
J a v a
45
Lock Precedence
Can prevent deadlock in transactional methods via resource-
J a v a
class Cell {
i n
long value;
P r o g r a m m i n g
}
synchronized(fst) {
synchronized (snd) {
long t = fst.value;
fst.value = snd.value;
snd.value = t;
}
}
}
}
46
Holding Locks
class Server {
double state;
J a v a
Helper helper;
public synchronized void svc() {
state = illegalValue;
i n
helper.operation();
P r o g r a m m i n g
state = legalValue;
}
}
Potential problems with holding locks during downstream calls
Safety: What if helper.operation throws exceptions?
Liveness: What if helper.operation causes deadlock?
C o n c u r r e n t
}
public synchronized Object take() {
P r o g r a m m i n g
private int a;
private Singleton(){ a = 1;}
P r o g r a m m i n g
return ref;
}
}
public int getA() {
synchronized(lock) { return a; }
}
public void setA(int v){
synchronized(lock) { a = v; }
}
}
49
State Dependence
Two aspects of action control:
J a v a
Design Steps:
P r o g r a m m i n g
There is not a
state, acquaintances
separate accept
mechanism in
message anAction { ... } Java. So must
accept
implement policies
policy control in action methods
themselves.
50
Examples of State-Dependent Actions
• Print a file
C o n c u r r e n t
52
Interfaces and Policies
Boring running example
J a v a
interface BoundedCounter {
static final long MIN = 0;
static final long MAX = 10;
i n
P r o g r a m m i n g
of checking it !inRightState
class BalkingCounter {
protected long count_ = MIN;
synchronized long value() { return count_;}
i n
}
}
// ...
void suspiciousUsage(BalkingCounter c) {
if (c.value() > BalkingCounter.MIN)
try { c.dec(); } catch (Failure ignore) {}
}
void betterUsage(BalkingCounter c) {
try { c.dec(); } catch (Failure ex) {cope();}
}
55
Collection Class Example
class Vec { // scaled down version of Vector
protected Object[] data_; protected int size_=0;
J a v a
Balking iterators
• Throw exception on access if collection was changed.
Implement via version numbers updated on each change
i n
Indexed traversal
• Clients externally synchronize when necessary
• But coupled to particular locking policies
Synchronized aggregate methods
• Support apply-to-all methods in collection class
• But deadlock-prone
57
Synchronized Traversal Examples
class App {
void printAllV1(XVec v) { // aggregate synch
v.applyToAll(new Procedure() {
public void apply(Object x) {
System.out.println(x);
C o n c u r r e n t
}});
}
... actions...
Introduces liveness concerns
return
• Relies on actions of other
threads to make progress
• Useless in sequential
programs
59
Guarding via Busy Waits
class UnsafeSpinningBoundedCounter { // don’t use
protected volatile long count_ = MIN;
J a v a
void inc() {
i n
}
void dec() {
while (count_ <= MIN); // spin
--count_;
}
}
Unsafe — no protection from read/write conflicts
C o n c u r r e n t
• Suspends thread
P r o g r a m m i n g
x
T1 T2
waitset
63
Interactions with Interruption
Effect of Thread.interrupt():
J a v a
Acquiring exitAcquire
Running Waiting
Lock
enterAcquire wait
C o n c u r r e n t
exitAcquire
Acquiring Running
Lock + +
Interrupted interrupted
interrupt enterAcquire interrupt
64
Fairness in Java
Fairness is a system-wide progress property:
J a v a
• Potential starvation
— A thread never gets a chance to continue because other
threads are continually placed before it in queue
• FIFO usually not strictly implementable on SMPs
• But JVM implementations usually approximate fairness
• Manual techniques available to improve fairness properties
65
Timeouts
Intermediate points between balking and guarding
J a v a
// ...
synchronized void inc() throws Failure {
i n
}
P r o g r a m m i n g
doPut(x);
}
P r o g r a m m i n g
for (;;) {
try { wait(waitTime); }
catch (InterruptedException e) {
return false;
}
if (!isFull()) break;
long now = System.currentTimeMillis();
C o n c u r r e n t
part1 subpart1
lock
i n
outer part2
client
P r o g r a m m i n g
Applications
• Applies recursively
i n
client
part1 subpart1
owner
i n
P r o g r a m m i n g
client part2
class Part {
protected Container owner_; // never null
i n
class Container {
class Part {
public void m() {
synchronized(Container.this){ bareAction();}
} } }
class Client {
void f(Part p) {
i n
}
}
Used in AWT
• java.awt.Component.getTreeLock()
— Breaks encapsulation
try { wait(); }
P r o g r a m m i n g
catch(InterruptedException ex) {}
}
class Whole {
final Part part_ = new Part();
whole
part
wait set: T ...
i n
holds lock to
P r o g r a m m i n g
• Avoiding deadlocks
— Offloading locks used for status indicators, etc
• Improving concurrency
— Reducing lock contention for host object
• Reducing granularity
— Enabling fine-grained concurrency control
80
Isolating Dependent Representations
Does Location provide strong enough semantic guarantees?
J a v a
x_ += dx; y_ += dy;
}
}
No protection from interleaving problems such as:
Thread 1: x=loc.x(); ...............; y=loc.y();
C o n c u r r e n t
81
Conservative Representation Updates
class XY { // immutable
private final double x_, y_;
J a v a
XY(double x, double y) { x_ = x; y_ = y; }
double x() { return x_; }
double y() { return y_; }
i n
}
P r o g r a m m i n g
class LocationV2 {
private XY xy_;
LocationV2(double x, double y) {
xy_ = new XY(x, y);
}
synchronized XY xy() { return xy_; }
C o n c u r r e n t
class LocationV3 {
J a v a
private XY xy_;
XY newp){
boolean success = (xy_ == oldp);
P r o g r a m m i n g
... actions...
i n
In each method:
P r o g r a m m i n g
85
Optimistic Counter
class OptimisticBoundedCounter {
private Long count_ = new Long(MIN);
J a v a
Long newc){
boolean success = (count_ == oldc);
P r o g r a m m i n g
int height_ = 0;
int width_ = 0;
void put(Object x) {
synchronized (lastLock_) {
last_ = last_.next = new Node(x);
}
}
C o n c u r r e n t
queue
J a v a
last
head
i n
value
(null)
Autonomous Loops
Oneway messages
Interactive messages
Most design ideas and semantics stem from active object models.
90
Autonomous Loops
Simple non-reactive active objects contain a run loop of form:
J a v a
doSomething();
}
P r o g r a m m i n g
}
public void run() {
for(;;) {
moveRandomly();
canvas.repaint();
try { Thread.sleep((int)(Math.random()*10);}
catch (InterruptedException e) { return; }
}
}
}
92
Particle Applet
import java.awt.*;
import java.applet.*;
J a v a
}
}
P r o g r a m m i n g
state, acquaintances
Client
accept react {
i n
Safety
Availability
Activity-based forces
Flow
Performance
same thread
C o n c u r r e n t
put take
98
Reactive Methods
Code scaffolding for illustrating patterns:
J a v a
class Host {
// ...
i n
// Assign to localState_;
}
updateState(...);
sendMessage(...);
}
i n
react
i n
... updateState...
P r o g r a m m i n g
start/run
process
C o n c u r r e n t
101
Multicast TPM
J a v a
return
C o n c u r r e n t
try {
ServerSocket socket = new ServerSocket(PORT);
for (;;) {
i n
class Handler {
void process(Socket s) {
InputStream i = s.getInputStream();
OutputStream o = s.getOutputStream();
// decode and service request, handle errors
s.close();
}
}
103
Thread Attributes and Scheduling
Each Thread has an integer priority
J a v a
attributes
i n
P r o g r a m m i n g
Thread
specific
attributes
}
static long setDelay(long t) {
currentGameThread().movementDelay_ = t;
}
}
class Ball { // ...
void move() { // ...
C o n c u r r e n t
Thread.sleep(GameThread.getDelay()));
}
}
class Main { ... new GameThread(new Game()) ... }
Define contextual attributes in special Thread subclasses
• Can be accessed without locking if all accesses are always
via Thread.currentThread()
• Enforce via static methods in Thread subclass
106
Using ThreadLocal
java.lang.ThreadLocal available in JDK1.2
J a v a
class Ball {
static ThreadLocal delay = new ThreadLocal();
void move() { // ...
C o n c u r r e n t
per Class
P r o g r a m m i n g
per Application
per Principal per Object
per Role
per Session
per Thread
per Group
per Method
per Site
per Block
C o n c u r r e n t
per Domain
per Aggregate
per System
per Version
108
Choosing among Scoping Options
Reusability heuristics
J a v a
• Responsibility-driven design
• Simplify Programmability
P r o g r a m m i n g
Conflict analysis
}
void sendMessage(...) { // no synch
P r o g r a m m i n g
to terminate, or
generate their own
threads ... updateState...
Host can respond to process
another react call from
another thread
immediately after
updating state
110
Using Pass-Throughs
Common approach to writing AWT Event handlers, JavaBeans
methods, and other event-based components.
J a v a
Variants
Bounded Thread-per-Message
• Keep track of how many threads have been created. If too
many, fall back to pass-through.
Mediated
• Register handlers in a common mediator structured as a
pass-through.
111
Multicast Pass-Throughs
class Host { //...
CopyOnWriteSet handlers_;
J a v a
}
P r o g r a m m i n g
void sendMessage(...) {
Iterator e = handlers_.iterator();
while (e.hasNext())
((Handler)(e.next())).process(...);
}
}
C o n c u r r e n t
Producer
Reactive method just places message in a channel
i n
}
Common variants
Pools
Use more than one worker thread
Listeners
Separate producer and consumer in different objects
113
Worker Thread Example
interface Channel { // buffer, queue, stream, etc
void put(Object x);
J a v a
Object take();
}
i n
void sendMessage(...) {
channel_.put(new Runnable() { // enqueue
public void run(){
handler_.process(...);
}});
}
C o n c u r r e n t
react
i n
... updateState...
P r o g r a m m i n g
put
take
run !empty
C o n c u r r e n t
run
process
115
Channel Options
Unbounded queues
J a v a
Synchronous channels
• Force client to wait for handler to complete previous task
Leaky bounded buffers
• For example, drop oldest if full
C o n c u r r e n t
Priority queues
• Run more important tasks first
Streams or sockets
• Enable persistence, remote execution
Non-blocking channels
• Must take evasive action if put or take fail or time out
116
Example: The AWT Event Queue Thread
AWT uses one thread and a single java.awt.EventQueue
J a v a
AWT queue
P r o g r a m m i n g
client
J a v a
put handler
i n
handler
P r o g r a m m i n g
channel take
handler
handler
C o n c u r r e n t
put take
i n
}
});
}
}
Listener() {
c = new ...
Thread me = new Thread(new Runnable() {
public void run() {
for (;;) {
((Runnable)(c.readObject())).run();
}}});
me.start();
}
}
122
Synchronous Channels
Synchronous oneway messages same as asynchronous, except:
J a v a
class SynchronousChannel {
J a v a
125
Interactive Messages
Synopsis
J a v a
client server
P r o g r a m m i n g
Applications
• Observer designs
changeValue(v)
The callbacks are state queries
Examples
i n
changeNotification
• Screen updates
P r o g r a m m i n g
val==v
• Constraint frameworks
return
• Publish/subscribe
• Hand-built variants of currentValue
wait and notifyAll
Notifications must use oneway
C o n c u r r e n t
127
Observer Example
class Subject {
J a v a
while (it.hasNext()){
final Observer o = (Observer)(it.next());
new Thread(new Runnable() {
public void run() {
o.changeNotification(this);
}
}).start();
}
}
} // More common to use pass-through calls instead of threads
128
Observer Example (Continued)
J a v a
class Observer {
protected double cachedState_;//last known state
protected Subject subj_; // only one here
i n
Observer(Subject s) {
P r o g r a m m i n g
app start/run
The callbacks are continuation
calls that transmit results
i n
return
• May contain a message ... try action...
P r o g r a m m i n g
ID or completion token to
tell client which task has success
completed completed
failed
130
Completion Callback Example
Callback interface
J a v a
interface FileReaderClient {
void readCompleted(String filename);
void readFailed(String filename,IOException ex);
i n
}
P r o g r a m m i n g
Sample Client
}
void readFailed(String fn, IOException e){
// ... deal with failure ...
}
void app() {
new Thread(new FileReader(“file”,
data_,this)).start();
}
}
131
Completion Callbacks (continued)
Sample Server
J a v a
void run() {
try {
C o n c u r r e n t
// ... read...
if (client_ != null)
client_.readCompleted(nm_);
}
catch (IOException ex) {
if (client_ != null)
client_.readFailed(nm_, ex);
}
}
}
132
Threads and I/O
Java I/O calls generally block
J a v a
— Socket.setSoTimeOut
• Can manually set up classes to arrange time-out interrupts
for other kinds of I/O
Common variants of I/O completion callbacks
• Issue callback whenever there is enough data to process,
rather than all at once
C o n c u r r e n t
class SvcAdapter {
Server server = new ServerImpl();
EHandler handler;
void attachHandler(EHandler h) { handler = h; }
public void svc() { // no throw clause
try { server.svc(); }
C o n c u r r e n t
catch (SException e) {
if (handler != null) handler.handle(e); }
}
}
Pluggable Handlers can do anything that a normal catch clause can
• Including cancelling all remaining processing in any thread
• But are less structured and sometimes more error-prone
134
Joining Threads
Thread.join() may be used instead of callbacks when
J a v a
try { t.join(); }
catch(InterruptedException e) { return; }
displayPicture(waiter.result);
}
}
136
Join Protocol
waiter
show start
i n
run
isAlive
P r o g r a m m i n g
render
return
C o n c u r r e n t
!isAlive
join
!isAlive
return
displayPicture(result)
...
137
Futures
Encapsulate waits for results of operations performed in threads
J a v a
img_ = img;
notifyAll();
}
public synchronized byte[] getImage() {
while (img_ == null)
try { wait(); }
catch (InterruptedException e) { ... }
return img_;
}
} // continued
138
Futures (continued)
// class AsynchRender, continued
J a v a
p.setImage(doRender(raw));
}
}).start();
return p;
}
• Applet.stop() called
P r o g r a m m i n g
Options
C o n c u r r e n t
class C {
i n
• But this would only work well if done after just about every
line of code in just about every Java class. Impractical.
thread.isInterrupted
i n
(static) Thread.interrupted
• Clears status for current thread, returning previous status.
thread.interrupt
• Sets interrupted status, and also causes applicable
methods to throw InterruptedException
C o n c u r r e n t
Thread.currentThread().interrupt()
C o n c u r r e n t
Alternatives
if (Thread.currentThread().isInterrupted())
cancellationCode();
• Also in loop headers of looping methods, etc
i n
try { somethingThrowingInterruptedException(); }
catch (InterruptedException ex) {
cancellationCode();
}
• Or as a subclass of a general failure exception, as in
InterruptedIOException
C o n c u r r e n t
Throwing InterruptedException
theSecurityMgr.denyAllChecksFor(t); // made-up
try { t.join(maxWaitToDie); }
catch(InterruptedException ex) {}
if (!t.isAlive()) return true;
— usually in Applet.stop
P r o g r a m m i n g
revisit/reload
killed when unloading after
finalized
destroy finalization
Guidelines
• Explicitly cancel threads (normally in Applet.stop)
• Ensure that activities check cancellation often enough
• Consider last-resort Thread.stop in Applet.destroy
147
Concurrent Application
Architectures
J a v a
Parallel execution
Partitioning independent tasks
— Illustrated with Group-based designs
Layered services
Synchronization and control of ground objects
— Illustrated with Before/After designs
148
Push Flow Systems
Systems in which (nearly) all activities are performed by objects
J a v a
Examples
P r o g r a m m i n g
contractor
Chain of command invoices payment
C o n c u r r e n t
Pipeline algorithms
Requires common directionality and locality constraints
• Precludes many safety and liveness problems
• Success relies on adherence to design rules
— potentially formally checkable
The simplest and sometimes best open systems protocol
149
Stages in Flow Systems
Every stage is a producer and/or consumer
Stages implement common interface
J a v a
— routed
May have multiple predecessors
C o n c u r r e n t
— collected
Normally require explicit linkages
— only one stage per connection
Each stage can define put using any appropriate oneway message
implementation pattern — may differ across stages
150
Exclusive Ownership of Resources
Elements in most flow systems act like physical resources in that
J a v a
• If you have one, then you can do something (with it) that
you couldn’t do otherwise.
i n
Examples
• Invoices
C o n c u r r e n t
• Network packets
• Tokens
• Mail messages
• Money
151
Accessing Resources
class Stage {
i n
Resource res;
void put(Resource r) { /* ... */ }
P r o g r a m m i n g
put(r) put(r)
stage1 stage2 stage1 stage2
152
Ownership Transfer
Transfer policy
J a v a
put(r) put(r)
stage1 stage2 stage1 stage2
access access
(null) (null)
resource resource
153
Assembly Line Example
J a v a
i n
P r o g r a m m i n g
start
J a v a
PushSource
putA
PushStage
putA
DualInput
PushStage
putB
DualInputAdapter(DualInputPushStage stage) {
stage_ = stage;
}
• Simplifies composition
SingleOutput
PushStage next1
i n
class SingleOutputPushStage {
protected PushStage next1_= null;
P r o g r a m m i n g
DualOutput
PushStage
next2
C o n c u r r e n t
class DualOutputPushStage
extends SingleOutputPushStage {
protected PushStage next2_ = null;
void attach2(PushStage s) { next2_ = s; }
}
Alternatively, could have used a collection (Vector etc) of nexts
We assume/require all attaches to be performed before any puts
157
Linear Stages
J a v a
putA putA
Painter next1
i n
P r o g r a m m i n g
public Painter(Color c) {
super();
color_ = c;
}
C o n c u r r e n t
putA
putA
Collector next1
i n
putB
P r o g r a m m i n g
try { wait(); }
catch (InterruptedException e){return null;}
a_ = p;
return tryJoin();
}
protected synchronized Box tryJoin() {
if (a_ == null || b_ == null) return null;
C o n c u r r e n t
putA next2
i n
implements PushStage {
HorizJoin Collector
Scatter/gather designs
163
Interacting with Groups
Group Proxies encapsulate a group of workers and protocol
J a v a
return
gather
int n = data.length;
Thread threads[] = new Thread[n];
P r o g r a m m i n g
results[i] = r.render(data[i]);
}
};
threads[i].start();
}
// block until all are finished
for (int k = 0; k < n; k++) threads[k].join();
return results;
}
}
165
Iteration using Cyclic Barriers
CyclicBarrier is synchronization tool for iterative group algorithms
J a v a
while (!done()) {
transform(data[i]);
try { barrier.barrier(); }
catch(InterruptedException e){return;}
combine(data[i],data[(i+1)%NWORKERS]);
} } };
new Thread(worker).start();
}
}
}
166
Implementing Cyclic Barriers
class CyclicBarrier {
J a v a
else {
count_ = initial_;
++resets_;
notifyAll();
return true; // return true if caller tripped
}
}
}
167
Layered Services
client
J a v a
part1 subpart1
Control
i n
client part2
P r o g r a m m i n g
Concurrency Control
locking, waiting, failing
Basic mechanisms
C o n c u r r e n t
void controlled() {
pre();
try { action(); }
i n
finally { post(); }
}
P r o g r a m m i n g
170
Template Method Before/After Designs
Subclassing is one way to implement
before/after containment designs AbstractService
J a v a
public service() {
• Superclass instance variables pre();
action();
and methods are “contained” post();
i n
in subclass instances }
protected pre();
P r o g r a m m i n g
protected action();
protected post();
Template methods
• Isolate ground code and
control code in overridable ConcreteService
protected methods override
pre() or action() or post();
• Public methods call control
C o n c u r r e n t
171
Readers & Writers Policies
J a v a
threads
read data
i n
P r o g r a m m i n g
write
Apply when
• Methods of ground class can be separated into readers
(accessors) vs writers (mutators)
C o n c u r r e n t
while (!allowReader())
P r o g r a m m i n g
try { wait(); }
catch (InterruptedException ex) { ... }
--waitingReaders_;
++activeReaders_;
}
C o n c u r r e n t
while (!allowWriter())
try { wait(); }
P r o g r a m m i n g
Examples
Sync
void acquire()
void release()
boolean attempt(long timeOut)
i n
P r o g r a m m i n g
cond
Service ConcreteSync
service(...) {
cond.acquire(); implementations
try { action(); }
finally { cond.release(); }
}
C o n c u r r e n t
Latches
i n
Barriers
Reentrant Locks
C o n c u r r e n t
Mutexes
• Non-reentrant locks
Read/Write Locks
Applications
C o n c u r r e n t
This uses native synch for update protection, but only inside permit
blocks. This avoids nested monitor lockouts
180
Semaphore Synchronous Channel
class SynchronousChannelVS {
J a v a
• Initialization flags
• End-of-stream conditions
i n
• Thread termination
P r o g r a m m i n g
• Event occurrences
class Worker implements Runnable {
Latch go;
Worker(Latch l) { go = l; }
public void run() {
go.acquire();
doWork();
C o n c u r r e n t
}
}
class Driver { // ...
void main() {
Latch go = new Latch();
for (int i = 0; i < N; ++i) // make threads
new Thread(new Worker(go)).start();
doSomethingElse(); // don’t let run yet
go.release(); // let all threads proceed
} }
182
Using Barrier Conditions
Count-based latches
J a v a
}
}
class Driver { // ...
void main() {
Barrier done = new Barrier(N);
for (int i = 0; i < N; ++i)
new Thread(new Worker(done)).start();
doSomethingElse();
done.acquire(); // wait for all to finish
} }
183
Using Lock Classes
class HandSynched {
private double state_ = 0.0;
J a v a
HandSynched(Sync l) { lock_ = l; }
i n
void changeState(double d) {
P r o g r a m m i n g
try {
lock_.acquire();
try { state_ = d; }
finally { lock_.release(); }
} catch(InterruptedException ex) { }
}
C o n c u r r e n t
double getState() {
double d = 0.0;
try {
lock_.acquire();
try { d = state_; }
finally { lock_.release(); }
} catch(InterruptedException ex){}
return d;
}
}
184
Wrapper Classes
Standardize common client usages of custom locks using wrappers
J a v a
• But need to create new interface type for each kind of block
C o n c u r r e n t
class WithLock {
Sync cond;
public WithLock(Sync c) { cond = c; }
i n
throws InterruptedException {
cond.acquire();
try { command.run(); }
finally { cond.release(); }
}
Runnable onInterrupt) {
try { perform(command); }
catch (InterruptedException ex) {
if (onInterrupt != null)
onInterrupt.run();
else // default
Thread.currentThread().interrupt();
}
}
}
186
Using Wrappers
class HandSynchedV2 { // ...
private double state_ = 0.0;
J a v a
HandSynchedV2(Sync l) {
i n
void changeState(double d) {
withlock_.perform(
new Runnable() {
public void run() { state_ = d; } },
null); // use default interrupt action
}
C o n c u r r e n t
double getState() {
// (need to define interface & perform version)
try {
return withLock_.perform(new DoubleAction(){
public void run() { return state_; } });
}
catch(InterruptedException ex){return 0.0;}
}
}
187
Using Conditional Locks
Back-offs
i n
Reorderings
class Cell {
J a v a
long value;
Sync lock = new SyncImpl();
void swapValue(Cell other) {
i n
for (;;) {
try {
P r o g r a m m i n g
lock.acquire();
try {
if (other.lock.attempt(100)) {
try {
long t = value; value = other.value;
other.value = t;
return;
C o n c u r r e n t
}
finally { other.lock.release(); }
}
}
finally { lock.release(); }
}
catch (InterruptedException ex) { return; }
}
}
}
189
Lock Reordering Example
class Cell {
long value;
J a v a
try {
if (!b.lock.attempt(0)) return false;
P r o g r a m m i n g
try {
long t = a.value;
a.value = b.value;
b.value = t;
return true;
}
finally { other.lock.release(); }
C o n c u r r e n t
}
finally { lock.release(); }
return false;
}
Sync writeLock();
}
i n
class WithRWLock {
ReadWriteLock rw;
public WithRWLock(ReadWriteLock l) { rw = l; }
rw.readLock().acquire();
try { readCommand.run(); }
finally { rw.readlock().release(); }
}
191
Transaction Locks
Associate keys with locks
J a v a
Sample interface
interface TransactionLock {
C o n c u r r e n t
interface Transactor {
i n
For example:
throws InsufficientFunds,
InterruptedException;
}
}
P r o g r a m m i n g
// ...
void deposit(long amount) throws ... {
tlock_.acquire(((XTG)
(Thread.currentThread().getThreadGroup()))
.getContext().get("TransactionID"));
synchronized (this) {
if (amount >= 0) balance_ += amount; else ...
}
}
}
195
Integrating Control Policies
Dealing with multiple contextual domains, including
J a v a
balance += amount;
lock.release();
db.commit(balance, ...);
UIObservers.notifyOfChange(this);
}
}
State tracking
Single notifications
Avoiding locks
Can lead to significantly faster, but more complex and fragile code
198
Tracking State in Guarded Methods
Partition action control state into categories with
same enabling properties
J a v a
top
dec inc
State Condition inc dec from
MAX
to
MAX
i n
bottom
Only provide notifications when making a state
transition that can ever unblock another thread
• Here, on exit from top or bottom
C o n c u r r e n t
199
Counter with State Tracking
J a v a
class FasterGuardedBoundedCounter {
protected long count_ = MIN;
i n
data_[putPtr_] = x;
putPtr_ = (putPtr_ + 1) % data_.length;
P r o g r a m m i n g
if (size_++ == 0) notifyAll();
}
throws InterruptedException {
put(x);
put(y);
i n
}
P r o g r a m m i n g
}
PutPair does not guarantee that the pair is inserted contiguously
To ensure contiguity, try adding guard:
while (size_ > data_.length - 2) wait();
But doTake only performs notifyAll when the buffer transitions
C o n c u r r e n t
else {
try { while (owner_ != null) wait(); }
catch (InterruptedException e) {
notify(); throw e;
}
owner_ = caller; holds_ = 1;
}
C o n c u r r e n t
}
synchronized void release() {
Thread caller = Thread.currentThread();
if (caller != owner_ || holds_ <= 0)
throw new Error("Illegal Lock usage");
if (--holds_ == 0) {
owner_ = null;
notify();
}
}}
204
Implementing Semaphores
final class Semaphore implements Sync {
int permits_; int waits_ = 0;
J a v a
Semaphore(int p) { permits_ = p; }
i n
++waits_;
try {
do { wait(); } while (permits_ == 0);
}
catch(InterruptedException ex) {
--waits_; notify(); throw ex;
}
C o n c u r r e n t
--waits_;
}
--permits_;
}
But can have surprising effects if callers expect locking for sake of
memory consistency.
final class Latch implements Sync {
private boolean latched_ = false;
synchronized(this) {
while (!latched_) wait();
}
}
int readers_ = 0;
Document decisions
• Use javadoc to link to more detailed descriptions
• Use naming and signature conventions as shorthand clues
• Explain deviations from standards, usage limitations, etc
• Describe necessary data invariants etc
Use checklists to ensure minimal sanity
209
Sample Documentation Techniques
Patlet references
J a v a
Representation inconsistencies
• Allowing dependent representations to vary independently
Invariant failures
• Failing to re-establish invariants within atomic methods
for example failing to clean up after exceptions
C o n c u r r e n t
Semantic conflicts
• Executing actions when they are logically prohibited
Slipped Conditions
• A condition stops holding in the midst of an action
requiring it to hold
Memory ordering and visibility
• Using stale cached values
212
Liveness Problems
Lockout
J a v a
Livelock
• A retried action never succeeds
Missed signals
• A thread starts waiting after it has already been signalled
C o n c u r r e n t
Starvation
• A thread is continually crowded out from passing gate
Failure
• A thread that others are waiting for stops
Resource exhaustion
• Exceeding memory, bandwidth, CPU limitations
213
Efficiency Problems
Too much locking
J a v a
Reusability Problems
Context dependence
J a v a
Policy breakdown
i n
Inflexibility
Policy clashes
strategies
Inheritance anomalies
Programmer-hostile components