Title: Distributed Software Engineering
1Confinement
2- Encapsulation technique to structurally guarantee
that at most one activity (thread) at a time can
possibly access a given object. - Ensure uniqueness of access
- No need to rely on dynamic locking (synch)
3Reference Leakage
- A reference r to an object x can escape from
method m executing some activity - m passes r as an argument to a method
- m passes r as the return value from a method
invocation - m records r in some field accessible from other
activity ( worst case static fields) - m releases another reference that can be
traversed to access r.
4Allowed leakage
- Some leakages are allowed if they guarantee no
state changes.
5Confinement across methods
- If a given method creates an object, and does not
let it escape, thus no other thread will
interfere with it - Hiding access within local scope
- You may allow to escape as a tail-call original
method will have no more use of reference. - Hand-off protocol at any time, at most one
actively executing method can access an object - Tail call
- Factory methods.
6Confinement across methods
- Sessions
- A public method creates an object confined to a
sequence of operation comprising the service - Method performs any cleanup needed via a finally
clause
7Confinement across methods
- Multiple calls tail calls do not apply if
calling method needs to access object after call.
- Caller copies -- identity is not needed
- Receiver copies -- ditto
- Using scalar arguments instead of references
- Provide enough information for receiver to
construct object if need by. - Trust
8Confinement within threads
- Thread-per-session design.
class ThreadPerSessionBasedService //
fragments // ... public void service()
Runnable r new Runnable() public void
run() OutputStream output null
try output new FileOutputStream(".
..") doService(output)
catch (IOException e)
handleIOFailure() finally
try if (output ! null) output.close()
catch (IOException ignore)
new Thread(r).start()
void handleIOFailure() void doService(OutputStr
eam s) throws IOException s.write(0)
// ... possibly more hand-offs ... // end
ThreadPerSessionBasedService
9Confinement within threads
- Thread-specific fields
- Static method Thread.currentThread()
- Add fields to thread subclass, and access them
within current thread.
10class ThreadWithOutputStream extends Thread
private OutputStream output
ThreadWithOutputStream(Runnable r, OutputStream
s) super(r) output s static
ThreadWithOutputStream current() throws
ClassCastException return
(ThreadWithOutputStream) (currentThread())
static OutputStream getOutput() return
current().output static void
setOutput(OutputStream s) current().output
s
11class ServiceUsingThreadWithOutputStream
// Fragments // ... public void service()
throws IOException OutputStream output
new FileOutputStream("...") Runnable r new
Runnable() public void run()
try doService() catch (IOException e)
new ThreadWithOutputStream(r,
output).start() void doService() throws
IOException ThreadWithOutputStream.current()
.getOutput().write(0)
12ThreadLocal
class ServiceUsingThreadLocal
// Fragments static ThreadLocal output new
ThreadLocal() public void service() try
final OutputStream s new
FileOutputStream("...") Runnable r new
Runnable() public void run()
output.set(s) try doService()
catch (IOException e)
finally try s.close()
catch (IOException ignore)
new Thread(r).start()
catch (IOException e) void
doService() throws IOException
((OutputStream)(output.get())).write(0) //
...
13Confinement within threads
- Housing object references in Thread objects allow
methods running in the same thread to share them
freely - Thread specific variables hide parameters and
makes hard error checking and leakage - No synchronization needed, but
- Hinders reusability as it increases coupling.
14Confinement within objects
- Can confine all access to be only internal to an
object, so no further locking is needed. - Exclusive control of host of container object
propagates to its internal parts. - Need synchronization at all entry points in the
Host object. - Host own the parts, or parts are contained in
Host. - Host constructs new instances of the parts,
- Host does not leak references
- Best host all parts are fixed. No need for
updates. - Typical implementation of such Host
- Use of adapters
- Use of subclassing
15Confinement within groups Adapters
- Can be used o wrap bare unsynchronized objects
within fully synchronized Hosts.
class BarePoint public double x public
double y class SynchedPoint protected
final BarePoint delegate new BarePoint()
public synchronized double getX() return
delegate.x public synchronized double getY()
return delegate.y public synchronized void
setX(double v) delegate.x v public
synchronized void setY(double v) delegate.y
v
- The Java.util.collection framework uses
adapter-based allowing layered synchronization of
collection classes. Except for Vector and
Hashtable, basic collection classes are
unsynchronized. Synchronized adapters can be
constructed - List l Collections.synchronizedList(new
ArrayList())
16Confinement within groups Adapters
- When you cannot guarantee containment, define
multiple versions of a class and instantiate
appropriately for given usage.
class SynchronizedAddress extends Address //
... public synchronized String getStreet()
return super.getStreet() public
synchronized void setStreet(String s)
super.setStreet(s) public synchronized
void printLabel(OutputStream s)
super.printLabel(s)
class Address //
Fragments protected String street protected
String city public String getStreet()
return street public void setStreet(String
s) street s // ... public void
printLabel(OutputStream s)
17Confinement within groups
- Groups of objects accessible across multiple
threads can together ensure that only one of them
can access a given resource - Tokens
- Batons
- Linear objects
- Capabilities
- Resources
- These groups need strict protocols to manage the
resource - Acquire
- Forget
- Put (give)
- Take
- Exchange