Characterizing Progress Properties of Concurrent Objects via Contextual Refinements
Concurrent access to Objects and variables
description
Transcript of Concurrent access to Objects and variables
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
1
Concurrent access to Objects and variables
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
2
Concurrent access
• With multi-threaded programming, threads can access same data, controls need to be in place to ensure that their access has the desired effects and the data remains consistent.
• Problems expected:– Current thread get preempted halfway its execution for
other thread to execute.– While thread is preempted, other thread access same
data (object’s instance variables) and performs changes in data that was or was being manipulated by preempted thread.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
3
Designing solutions
1. Make operations atomic (to avoid race conditions: two threads sending same message to same object at the same time and behavior of code depends on who wins)
2. Do not allow a thread to be suspended in the middle of an operation while giving access to another thread to perform operations on same data.
• Warning: these solutions create their own set of new problems.
• Hard news: we need the solutions proposed but need to deal with the problems created by them.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
4
Multi-threaded programming properties• Safety : nothing bad ever happens
– Safety failure:Unintended behavior at run time– Desired goal: all object states are consistent.
• Liveness: anything ever happens– Liveness failure: things just stop running– Desired goal: all threads have their chance to run to expected
completion.• These properties need to be balanced
– But: better do nothing (liveness failure) that something that leads to a safety failure
– On the other hand: there are many situations where is better to give an incorrect answer than not one at all.
• Warning: some of the easiest thing to improve liveness property can destroy safety property and viceversa.
• Get them both right is the challenge in Multi-threaded programming.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
5
Multi-threaded software properties
• On top of these two fundamental multi-threaded programming properties, we have the following two software eng. Properties:
1. PerformanceThe extend to which activities execute soon and quickly.
2. ReusabilityThe utility of objects and classes across multiple contexts.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
6
Programming gets harder
• Most multi-threaded safety matters cannot be checked automatically
• Must rely on the programmer and design being implemented: – Strong hint: design up-front. – Design vs. code ratio: 10 – 1
• There are many methodologies to prove manually that designs are safe. We will cover some during this course.
• But most importantly: safety properties relies strongly on the software engineering practices by the programmers.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
7
Maintaining object’s consistency• Sometime hard to completely establish what is legal and
meaningful for a class• Better route: establish conceptual-level invariants.
(Example: volume for water tank must be between zero and capacity)• Object’s consistency follows preservation of their
invariants: an object is consistent if all fields obey their invariants.
• To uncover invariants:– Clearly understand object’s properties– Constraints on object’s representation
• Note: safe objects may occasionally enter transiently inconsistent states, in the mist of methods; but they never attempt to initialize new actions while inconsistent.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
8
Importance of Object’s invariants
• One reason for being more careful about invariants in multi-threaded programming: it is much easier to break them than in sequential programming.
• Remainder: the need of protection against inconsistency also arises in sequential programming:– Processing exceptions– Making callbacks– Self-calls between methods in a class.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
9
Maintaining consistency: Exclusion
• Guaranteeing atomicity
• Failures of maintaining atomicity:– Read/Write conflicts– Write/Write conflicts
• Impossible to predict the consequences of actions when objects are inconsistent.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
10
Liveness
• Goal: every activity eventually progresses towards completion
• But an activity may fail (even transiently) for any number of possibly interrelated reason
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
11
Liveness failures
• Locking• Waiting for a condition• Input from another device • CPU contention• Failure due to exception, error or fault.• But:
– Temporal blocking of progress is expected, but this blocking time cannot be unbounded.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
12
Potential permanent liveness failures
• Deadlock : circular dependencies– Thread A hold a lock for object X, and needs to acquire
and lock object Y– Thread B already locks object Y, and needs to acquire
lock for object X.
• Missed signals: thread started waiting after given notification to wake up was given.
• Nested monitor lockouts: waiting thread holds lock needed by another thread attempting to wake it up.
• Livelock: continuously retried action continuously fails.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
13
Potential permanent liveness failures
• Starvation
• Resource exhaustion
• Distributed failure: a remote server machine connected by a socket crashes or otherwise becomes inaccessible.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
14
Performance
• Throughput: number of ops/unit of time• Latency: time elapsed between issuing a message
and its execution• Capacity: number of simultaneous activities• Efficiency: throughput/(#comp resources)• Scalability: rate at which latency and throughput
improve when resources are added to system.• Degradation: rate at which latency or throughput
worsens as more clients, activities, operations are added without adding resources.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
15
Efficiency trade-off
• Poorer efficiency for better latency, and scalability– Locks– Monitors– Threads– Context-switching– Scheduling– Locality– Algorithmics
• All the above reduce efficiency due to overhead and contention that can slow down program.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
16
Strategies for safety in objects
• Immutability– Avoid state changes.
• Synchronization– Dynamically ensuring exclusive access.
• Containment– Structurally ensuring exclusive access.
• Variants:– Stateless methods– Partial synchronization– Managed ownership
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
17
Immutable Objects
• To avoid synchronization, do not change the state of the objects.– Programs are easier to understand– But, these programs are unable to handle user
interactions, cooperating threads, etc.
• But we can at least search for: selected immutability.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
18
Simplest immutable objects
• Do not have state at all.• Their methods are stateless; they are given data
through parameters. Such data is primitive type data or object reference which are not updated by the method.
Class StatelessAdder {public int add(int a, int b) { return a + b;}
}
• Methods are always safe and live
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
19
Simplest immutable objects
• This safety and liveness also hold for classes with only final fields.
class ImmutableAdder {
public ImmutableAdder (int a) { offset = a;}
public int addOffset(int b) {
return offset + b;
}
private final int offset;
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
20
Immutability in API’s
• ADT’s implementing values: colors, strings. These classes are called Value containers.
• Can create a numeric class where the methods never alter their fields but construct and return values as the result of the methods.
• Design different classes supporting different usages: provide immutable and updateable versions: String, StringBuffer.
• Protect objects via copying, when is rarely done and is cheap.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
21
Immutability for sharing
• Immutability is a useful technique for sharing values and avoid costs associated from exclusion in multi-threaded programming. (MTP)
• Instances of many utility classes in MTP are intrinsically immutable and shared by many other objects.
class Relay {public Relay ( Server s) { server = s;}public void execute() { server.execute();}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
22
Constructing immutable objects
• Fields must be final• Do not allow fields to be accessed until
construction is completed. (must lock)• Field values must be copied (or can use
references if values are immutable themselves)
• Constructors depending on the construction of other objects must relay on locking.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
23
Immutability variant: stateless methods
• A mutable object can provide services via strictly stateless methods, ie, have no bearing on the object’s state.
• Stateless methods can be used as if they where methods of an immutable object.
• Stateless methods often make copies of arguments and results.
• Copying only works if it is to be used locally. • Java does not provide pass-by-copy parameter
passing mechanism, so it is left up to the programmer.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
24
Basic concepts: atomic operations (atomicity).
• Atomic operations can't be interrupted (divided)– In java assigment to int, boolean is atomic– But assignment to double or long is not atomic
long x;• thread 1 may attempt to execute:x = 0x0123456789abcdef• thread 2 may attempt to execute :x = 0;• possible results:0x0123456789abcdef;0x0123456700000000;0x0000000089abcdef;0x0000000000000000;
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
25
64-bit assignment
• 64-bit assignment is effectively implemented as:
x.high = 0x01234567
x.low = 0x89abcdef;• You can be preempted between the
assignment operations, unless you lock.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
26
Basic concepts: synchronization• Mechanism to provide locking or exclusion by other threads
while a thread is executing some common code.• Mechanisms to assure that multiple threads:
– Start execution at the same time and run concurrently ("condition variables" or "events").
– Do not run simultaneously when accessing the same object ("monitors").
– Do not run simultaneously when accessing the same code ("critical sections").
• The synchronized keyword is essential in implementing synchronization (but is poorly designed.)
– No timeout, so deadlock detection is impossible.– There is no way to determine if an object is already lock due
to synchronization– If an object attempts to lock an already lock object, it is
placed in a list waiting to acquire the lock, but no thread can be removed from that list by client.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
27
Example of need to exclude
public class Even {/**
* ensure: nVal() % 2 == 0 */public void next() {
++n;++n;
}public int nVal(){return n;
}private int n = 0;
}
Typical behavior:This code might work well most of the time, and possibly only rarely will exhibit safety failure.When it does: hard to debug, as the inconsistency is usually manifested in other unrelated objectstate.
Solution:
Declare next() synchronized. This excludes access to this code by one thread when other thread is executing it: becomes atomic.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
28
Locks and Objects
• Every object instance has ONE LOCK and only one.
• Scalar fields can only be locked via their enclosing object instance.
• Methods and blocks of code can be marked as synchronized; fields are not.
• Arrays are objects as is Class object.• Locking an array of objects does not automatically
lock all its elements.• There are NO constructs for simultaneously
locking multiple objects in a single atomic op.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
29
Lock ownership
• An object’s lock is held (owned) by the thread executing synchronized code of the object.
• Thus, same thread can call other synchronized methods of the same object.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
30
Block synchronization• A block of code can be synchronized, but it takes an argument on
which object to block. Very commonly the object is this
synchronized(obj) {
//code to lock
}
Semantics:
1. No other thread can execute block concurrently.
2. No other synchronized method or block of code can be executed by any other thread on same object.
• Block synchronization can be done on any object
– Use it for protecting access to objects with no synchronized methods.
– For synchronizing a series of accesses to an object.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
31
Synchronization and inheritance• The synchronized keyword is not part of the method
signature• It is NOT a method modifier• It is not inheritable• Methods in interfaces cannot be specified synchronized• Constructors can not be synchronized either, but block
synchronization can be used within.• Synchronized instance methods in subclasses employ the
same lock as those in the superclass.• Synchronizing an inner class method is independent of its
outer class. • Inner classes can use a block with the instance of the outer
lock as the object to lock.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
32
Acquiring and releasing lock• Lock is acquired on entry to method or block.• Lock is released on exit of synchronized code, including exit due to an
exception.• Locks are per-thread not per invocation of method.
– A thread hitting synchronized accesses such code if:• No thread has the lock on the object for such code. OR• Same thread already possesses the lock of such object.
– Therefore, a thread possessing an object’s lock can make recursive calls without being locked out.
• a synchronized method or block obeys these rules only with respect to other synchronized methods or blocks on the same object.– Methods not synchronized still can execute at any time by any
other thread even if synchronized code is executing. • Any thread locked out due to a synchronized code will be place on
“hold in a queue”• When the object’s lock is released, there is no guarantee on which
thread will acquire the lock next. No fairness, but indeterminancy.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
33
Static fields or methods and synchronization
• Object synchronization does not affect static class fields or methods
• Static class fields or methods are synchronized with the lock of the Class object for that class.
• When synchronizing a static method it acquires a different lock than the lock for any object of that class; but all static methods will use same lock.
• A static block can be used against the lock of the object Class for that class.
• Example: having class C– synchronized (C.class) {….}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
34
Fully synchronized objects
• Safest (but might not be the best) multi-threaded strategy is to restrict attention to fully synchronized objects:– All public methods are synchronized– There are no public fields or other encapsulation
violations– All methods terminate– All fields are initialized to a consistent state in the
constructors– State of object is consistent (obey invariants) at both
the beginning and end of each method, even in the presence of exceptions.
• But this use costs and may lead to deadlocks.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
35
Code execution exclusion via synchronization
• With synchronized code declaration, two or more threads are guarantee not to interfere with each other on the same object.
• If an object has synchronized methods and two threads invoke such methods simultaneously on the same object, synchronization guarantees exclusion but it does not guarantee order of execution.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
36
Constructors and Synchronization
• Constructors are not synchronized because it is executed only when creating an object, which can only happen in one thread executing the creation.
• Constructors cannot be synchronized.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
37
Synchronization
• Always lock during updates to objects.
• Always lock during access of possibly updated object fields.
• Never lock when invoking methods on other objects.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
38
Basic concepts: semaphores
A semaphore is any object that two threads can use to synchronize with one another.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
39
The mutex (mutual-exclusion semaphore)
• The mutex is the key to a lock– Though it is sometimes called a “lock.”
• Ownership is the critical concept– To cross a synchronized statement, a thread must have
the key, otherwise it blocks (is suspended).– Only one thread can have the key (own the mutex) at a time.
• Every Object contains an internal mutex:Object mutex = new Object();synchronized( mutex ){ // guarded code is here.}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
40
Monitors and airplane bathrooms
• A monitor is a body of code (not necessarily contiguous), access to which is guarded by a single mutex.– Every object has its own monitor (and its own mutex).
• Think “airplane bathroom”– Only one person (thread) can be in it at a time– Locking the door acquires the associated mutex. – You can't leave without unlocking the door.– Other people must line up outside the door if somebody's in there.
– Acquisition is not necessarily FIFO order.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
41
Synchronization with individual locks
• Enter the monitor by passing over the synchronized keyword: I.e. acquiring an object’s lock, – Object has a synchronized method and a client invoked
such method– Client is executing a synchronized block on an object
• Entering the monitor does not restrict access to objects used inside the monitor—it just prevents other threads from entering the monitor.
long field;Object lock = new Object();synchronized(lock) {
field = new_value;}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
42
Method-level synchronization
• The monitor is associated with the object, not the code.– Two threads can happily access the same synchronized
code at the same time, provided that different objects receive the request.
– E.g. Two threads can enqueue to different queues at the same time, but they cannot simultaneously access the same queue:
– Same as synchronized(this)
class Queue{
public synchronized void enqueue(Object o){ /*…*/ }
public synchronized Object dequeue(){ /*…*/ }
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
43
He came in the Bathroom Window
• The Bathroom can have several doors
class Bathroom_window{
private double guard_this;
public synchronized void ringo(double value){ guard_this = value;
}
public double george(){// WRONG!
return guard_this; // needs synchronization
}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
44
Constructors can’t be synchronized, so always have back doors
class Unpredictable{private final int x;private final int y;public Unpredictable(int init_x, int init_y){ new Thread(){
public void run(){ System.out.println(“x=“ + x +
“ y=“ + y);}
}.start();x = init_x;y = init_y;
}}• Putting the thread-creation code at the bottom doesn’t help (the
optimizer might move it).
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
45
Locking the constructor’s back doorclass Predictable{
private final int x;private final int y;public Predictable(int init_x, int init_y){
synchronized( this ){ new Thread(){
public void run(){ synchronized( Predictable.this)
{ System.out.println(“x=“+x+“ y=“+y);
}}
}.start(); x = init_x; y = init_y;}
}}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
46
Synchronization isn’t cheap
class Synch { synchronized int locking ( int a, int b ) { return a + b;}int not_locking ( int a, int b ) { return a + b;}
static public void main(String[] arguments){ Synch tester = new Synch();double start = new Date().get Time();for(long i = 1000000; --i >= 0 ;)
tester.locking(0,0);double end = new Date().getTime();double locking_time = end - start;// repeat for not_locking
}}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
47
Synchronization isn’t cheap
• % java -verbose:gc Synch• Pass 0: Time lost: 234 ms. 121.39% increase• Pass 1: Time lost: 139 ms. 149.29% increase• Pass 2: Time lost: 156 ms. 155.52% increase• Pass 3: Time lost: 157 ms. 155.87% increase• Pass 4: Time lost: 157 ms. 155.87% increase• Pass 5: Time lost: 155 ms. 154.96% increase• Pass 6: Time lost: 156 ms. 155.52% increase• Pass 7: Time lost: 3,891 ms. 1,484.70% increase• Pass 8: Time lost: 4,407 ms. 1,668.33% increase• 200MHz Pentium, NT4/SP3, JDK 1.2.1, HotSpot 1.0fcs, E• • Contention in last two passes (Java Hotspot can’t use• atomic-bit-test-and-set).
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
48
Synchronization isn’t cheap
BUT• The cost of poor design is always higher than
the cost of synchronization.– Pick a fast algorithm.
• Overhead can be insignificant when the synchronized method is doing a time-consuming operation.– But in OO systems, small synchronized methods
often chain to small synchronized methods.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
49
Avoiding synchronization
• Reentrant code doesn’t need to be synchronized.– Code that uses only local variables and arguments (no static variables, no fields in the class).
– Atomic operations do not need to be synchronized, but beware of reordering.
– Assignment to all non-64-bit things, including booleans and references are usually safe, but sequence not preserved.
– Must be declared volatile, but volatile might not work.– Assignment to volatile doubles and floats should be
atomic (but most JVMs don’t do it).– Code may be reordered, so assignment to several atomic variables
must be synchronized.• Sequence of volatile operations should be preserved, but usually isn’t.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
50
Avoiding synchronization
• Synchronize the smallest block possible to minimize the odds of contention.– Method-level synchronization should be avoided in very-
high-performance systems.– Don’t synchronize the methods of classes that are called
only from one thread.– Use Collection-style synchronization decorators when you
need synchronized behavior.
• Collection c = new ArrayList();• c = Collections.synchronizedCollection(c);
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
51
Avoiding synchronization
• Don’t access synchronized methods from synchronized methods.– Synchronize public methods. Don’t synchronize private
ones.– Don’t use protected.– Avoid Vector and Hashtable in favor of Collection
and Map derivatives.– Don’t use BufferedInputStream, BufferedOutputStream, BufferedReader, or BufferedWriter unless the stream is shared between multiple threads.
• You can use InputStream’s read(byte[])• You can roll your own decorators.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
52
Critical sections
static final Object critical_section = new Object();
synchronized( critical_section ) {
// only one thread at a time can execute this code
}• A critical section is a body of code that only one thread can enter at
a time.• Do not confuse a critical section with a monitor.
– The monitor is associated with an object– A critical section guards code
• The easiest way to create a critical section is by synchronizing on a static field
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
53
Critical sections can also synchronize onthe class object
class Flintstone{ public void fred(){
synchronized( Flintstone.class ){ // only one thread at a time can
execute this code}
}public static synchronized void wilma() {
// synchronizes on the same object as fred().}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
54
Class vs. instance variables
• All synchronized static methods synchronize on the same monitor.
• Think class variables vs. instance variables:
– The class (static) variables and methods are effectively members of the Class object.
– The class (static) variables store the state of the class as a whole.
– The class (static) methods handle messages sent to the class as a whole.
– The instance (non-static) variables store the state of the individual objects.
– The instance (non-static) methods handle messages sent to the individual objects.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
55
But remember the bathroom with multipledoors
class Foo{ static long x = 0;
synchronized static void set_x( long x ){ this.x = x;
}synchronized /* not static */ double get_x(){
return x;}
}Thread 1: Thread 2:Foo o1 = new Foo(); Foo.set_x(-1);long x = o1.get_x();• Results are undefined. (There are two locks here, one on
the class object and one on the instance.)
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
56
Lock the extra doors
• Access all static fields through synchronized static methods, even if the accessor is a method of the class that contains the field.
class Okay{ private static long unsafe;private static synchronized get() {return unsafe;}private static synchronized set(long x) {unsafe = x;}
public /*not static*/ void foo(long x){ //...
set(x);}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
57
Lock the extra doors
• Synchronize explicitly on the class object when accessing a static field from an instance method.
class Okay { private static long unsafe;public void foo(long x){ //...
synchronized( Okay.class ){ unsafe = x;
}}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
58
Lock the extra doors
• Encapsulate all static fields in an inner class and provide exclusive access through synchronized methods of the inner
class. class Okay {
private class Class_Variables{ private long unsafe;public synchronized void do_something(long
x){ unsafe = x; //. . .}
}static Class_Variables statics = new Class_Variables();public foo(long x) {
statics.do_something( x );}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
59
Singletons (one-of-a-kind objects)
• Singletons often use critical sections for initialization.
public final class Singleton{ static{new JDK_11_unloading_bug_fix(Std.class);}private static Singleton instance;private Singleton(){} // prevent creation by newpublic synchronized static Singleton instance(){ if( instance == null )instance = new Singleton();return instance;}}Singleton s = Singleton.instance()
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
60
Synchronization and Collection API
• Methods in this collection are not synchronized by design to avoid overhead.
• There are several static methods in java.util.collections class that are used to wrap unsynchronized Collection instances with synchronized methods:
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
61
Synchronization and Collection API
static Collection synchronizedCollection(Collection c)
Returns a synchronized (thread-safe) collection backed by the specified collection.
static List synchronizedList(List list)
Returns a synchronized (thread-safe) list backed by the specified list.
static Map synchronizedMap(Map m)
Returns a synchronized (thread-safe) map backed by the specified map.
static Set synchronizedSet(Set s)
Returns a synchronized (thread-safe) set backed by the specified set.
static SortedMap synchronizedSortedMap(SortedMap m)
Returns a synchronized (thread-safe) sorted map backed by the specified sorted map.
static SortedSet synchronizedSortedSet(SortedSet s)
Returns a synchronized (thread-safe) sorted set backed by the specified sorted set.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
62
Thread deadlock
• Most common scenario:– Two threads are waiting for each other to finish
doing something, so that locks are released.
• Nested monitor lockout– (A one thread problem) The common situation
occurs when you call a blocking function within a synchronized method, and the only way to release the block is to call another synchronized method.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
63
Example
public class BlackHole {
…public synchronized void put( Object thing) {
queue.enqueue(thing);
}
public synchronized void get () {
return queue.dequeue();
}
…
private Queue queue;
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
64
Example
• This situation occurs anytime you have a blocking call ( such as a file read, a socket) inside a synchronized method.
class BlackHole{private InputStream input;public blackHole(){
Input = new Socket (“www.cs.uno.edu”, 80).getInputStream();
}public synchronized int read() {
Return input.read();}public synchronized void close() {
input.close();}
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
65
Nested monitor blocks
• Do not make blocking calls in synchronized methods.
• Make sure there is a way to talk to the blocking object via another class or a non-synchronized method.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
66
Deadlock on a Blocking I/O
• Once a read has been issued, it will block until data is read or there is an indication of end of file.
• If no data is coming in, read will block and there is no way to make it quit, short of aborting program.
• So, you must be very careful designing threads with I/O sequences of operations to execute.
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
67
Stopping threads
• stop() is deprecated for very good reasons.• Use t.interrupt() to stop a thread. • Your thread should test if is interruted.Class StopRight {
Private thread t = new Thread() {Public void run() {
Try{While (!this.isInterrupted()) { // blocking call}
} catch(InterruptedException e) { //ignore}}
}Public stop() { t.interrupt(); }
}
Spring/2002 Distributed Software EngineeringC:\unocourses\4350\slides\DefiningThreads
68
Exception and threads
• An uncaught exception in a thread will terminate the run() method, with a stack dump, but will not terminate the application.
• Not a good situation– App user may not understand the stack dump.– It may not be known that thread terminated
abnormally.