Concurrency State Models Java Programs
Concurrency State Models Java Programs
net/publication/236896079
CITATIONS READS
760 7,785
2 authors:
All content following this page was uploaded by Jeff Kramer on 06 May 2014.
State Models and Java Programs Performance gain from multiprocessing hardware
A sequential program has a
single thread of control. parallelism.
♦ Monitors & Condition Synchronization Models State models for the examples Jeff Magee &
Labelled Transition System Analyser (LTSA) for Jeff Kramer
♦ Deadlock Practice modeling concurrency, model animation and model
♦ Safety and Liveness Properties WILEY
property checking.
♦ Model-based Design
♦ Dynamic systems ♦Concurrent Software Architectures
♦ Message Passing ♦Timed Systems
Concurrency: introduction 10 Concurrency: introduction 11 Concurrency: introduction 12
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Summary
Concepts
we adopt a model-based approach for the design and
construction of concurrent programs
Models
we use finite state models to represent concurrent behavior.
Practice
we use Java for constructing concurrent programs.
Models are described using state machines, If x is an action and P a process then (x-> P)
A process is the execution of a sequential program. It is
known as Labelled Transition Systems LTS. modeled as a finite state machine which transits from describes a process that initially engages in the action
These are described textually as finite state state to state by executing a sequence of atomic actions. x and then behaves exactly as described by P.
processes (FSP) and displayed and analysed by on
the LTSA analysis tool.
a light switch
ONESHOT = (once -> STOP). ONESHOT state
machine
♦ LTS - graphical form
once
0 1 LTS
(terminating process)
♦ FSP - algebraic form 0 1
off
a sequence of
off
on on
off
on
off
………. actions or trace Convention: actions begin with lowercase letters
PROCESSES begin with uppercase letters
Concurrency: processes & threads 4 Concurrency: processes & threads 5 Concurrency: processes & threads 6
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
FSP - action prefix & recursion animation using LTSA FSP - action prefix
Repetitive behaviour uses recursion: on The LTSA animator can be FSP model of a traffic light :
used to produce a trace. TRAFFICLIGHT = (red->orange->green->orange
SWITCH = OFF,
0 1 Ticked actions are eligible -> TRAFFICLIGHT).
OFF = (on -> ON),
ON = (off-> OFF). for selection.
LTS generated using LTSA:
off
In the LTS, the last action is
red orange green
Substituting to get a more succinct definition: highlighted in red.
SWITCH = OFF,
on
0 1 2 3
OFF = (on ->(off->OFF)).
0 1
And again: Trace: orange
FSP model of a drinks machine : Process (x-> P | x -> Q) describes a process which
If x and y are actions then (x-> P | y-> Q) DRINKS = (red->coffee->DRINKS engages in x and then behaves as either P or Q.
describes a process which initially engages in either of |blue->tea->DRINKS
the actions x or y. After the first action has ). COIN = (toss->HEADS|toss->TAILS),
occurred, the subsequent behavior is described by P if blue
HEADS= (heads->COIN), toss
the first action was x and Q if the first action was y. LTS generated using LTSA: TAILS= (tails->COIN).
red
toss
Tossing a
Who or what makes the choice? 0 1 2 coin. 0 1 2
Is there a difference between input and
output actions? Possible traces? coffee
Possible traces?
heads
tea
Concurrency: processes & threads 10 Concurrency: processes & threads 11 Concurrency: processes & threads tails 12
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Modeling failure FSP - indexed processes and actions FSP - constant & range declaration
in.1.1
How do we model an unreliable communication channel Single slot buffer that inputs a value in the range 0 to 3
index expressions to in.1.0
which accepts in actions and if a failure occurs produces and then outputs that value: in.0.1
model calculation:
no output, otherwise performs an out action? BUFF = (in[i:0..3]->out[i]-> BUFF). in.0.0
equivalent to
Use non-determinism... in
BUFF = (in[0]->out[0]->BUFF 0 1 2 3
|in[1]->out[1]->BUFF
|in[2]->out[2]->BUFF out.0
0 1 const N = 1
in |in[3]->out[3]->BUFF
range T = 0..N
). out.1
CHAN = (in->CHAN range R = 0..2*N
|in->out->CHAN out or using a process parameter with default value: out.2
). stop STOP
inc inc inc stop
start tick tick tick beep
0 1 2 3
0 1 2 3 4 5
dec dec dec
Concurrency: processes & threads 16 Concurrency: processes & threads 17 Concurrency: processes & threads 18
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
FSP - process alphabets 2.2 Implementing processes Implementing processes - the OS view
The alphabet of a process is the set of actions in Modeling processes as O S Proc ess
which it can engage. finite state machines
using FSP/LTS. D ata C ode D escriptor
Alphabet extension can be used to extend the implicit Stack Stack Stack
alphabet of a process:
Implementing threads D escriptor D escriptor D escriptor
WRITER = (write[1]->write[3]->WRITER) in Java.
T hread 1 T hread 2 T hread n
+{write[0..3]}.
A (heavyweight) process in an operating system is represented by its code,
Alphabet of WRITER is the set {write[0..3]} Note: to avoid confusion, we use the term process when referring to data and the state of the machine registers, given in a descriptor. In order to
(we make use of alphabet extensions in later chapters) the models, and thread when referring to the implementation in Java. support multiple (lightweight) threads of control, it has multiple stacks, one
for each thread.
Concurrency: processes & threads 19 Concurrency: processes & threads 20 Concurrency: processes & threads 21
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
A Thread class manages a single sequential thread of control. Since Java does not permit multiple inheritance, we often An overview of the life-cycle of a thread as state transitions:
Threads may be created and deleted dynamically. implement the run() method in a class not derived from Thread but
new Thread() start() causes the thread to call its
from the interface Runnable.
run() method.
The Thread class executes instructions from its method target
Thread Runnable Thread start()
run(). The actual code executed depends on the Created Alive
implementation provided for run() in a derived class. run() public interface Runnable {
run()
public abstract void run(); stop(), or
class MyThread extends Thread { } st
op run() returns
public void run() { ()
//...... MyRun class MyRun implements Runnable{
MyThread } public void run() { Terminated
} run() The predicate isAlive() can be
//.....
run() } used to test if a thread has been started but
Thread x = new MyThread(); } not terminated. Once terminated, it cannot
be restarted (cf. mortals).
Thread x = new Thread(new MyRun());
Concurrency: processes & threads 22 Concurrency: processes & threads 23 Concurrency: processes & threads 24
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
thread alive states in Java Java thread lifecycle - an FSP specification Java thread lifecycle - an FSP specification
start yield
Once started, an alive thread has a number of substates : THREAD = CREATED,
sleep
CREATED = (start ->RUNNING stop suspend resume
start() |stop ->TERMINATED),
Running s
su lee RUNNING = ({suspend,sleep}->NON_RUNNABLE
sp p
en () |yield ->RUNNABLE 0 1 2 3 4
d( run
) |{stop,end} ->TERMINATED
yield() dispatch |run ->RUNNING),
RUNNABLE = (suspend ->NON_RUNNABLE end, run, stop suspend
suspend() end
|dispatch ->RUNNING dispatch are
Runnable Non-Runnable
resume() |stop ->TERMINATED), not methods of stop dispatch
3.1 Modeling Concurrency parallel composition - action interleaving parallel composition - action interleaving
scratch
How should we model process execution speed? think talk
If P and Q are processes then (P||Q) represents the ITCH CONVERSE
arbitrary speed
concurrent execution of P and Q. The operator || is 0 1 0 1 2
(we abstract away time) the parallel composition operator. 2 states scratch
3 states
Multi-party synchronization: A composite process is a parallel composition of primitive a:P prefixes each action label in the alphabet of P with a.
MAKE_A = (makeA->ready->used->MAKE_A). processes. These composite processes can be used in the
MAKE_B = (makeB->ready->used->MAKE_B). definition of further compositions. Two instances of a switch process:
ASSEMBLE = (ready->assemble->used->ASSEMBLE). SWITCH = (on->off->SWITCH).
||MAKERS = (MAKE_A || MAKE_B).
||FACTORY = (MAKE_A || MAKE_B || ASSEMBLE). ||TWO_SWITCH = (a:SWITCH || b:SWITCH).
a.on b.on
makeA ||FACTORY = (MAKERS || ASSEMBLE).
a:SWITCH b:SWITCH
0 1 0 1
Substituting the definition for MAKERS in FACTORY and applying the
makeB makeA ready assemble commutative and associative laws for parallel composition results in a.off b.off
the original definition for FACTORY in terms of primitive processes.
0 1 2 3 4 5 An array of instances of the switch process:
||FACTORY = (MAKE_A || MAKE_B || ASSEMBLE). ||SWITCHES(N=3) = (forall[i:1..N] s[i]:SWITCH).
||SWITCHES(N=3) = (s[i:1..N]:SWITCH).
Concurrency: concurrent execution makeB 10 Concurrency: concurrent execution 11 Concurrency: concurrent execution 12
used ©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
process labeling by a set of prefix labels process prefix labels for shared resources action relabeling
a.acquire a.use b.acquire b.use
a:USER
{a1,..,ax}::P replaces every action label n in the b:USER
Relabeling functions are applied to processes to change
0 1 2 0 1 2
alphabet of P with the labels a1.n,…,ax.n. Further, the names of action labels. The general form of the
every transition (n->X) in the definition of P is relabeling function is:
a.release b.release
replaced with the transitions ({a1.n,…,ax.n} ->X). b.acquire /{newlabel_1/oldlabel_1,… newlabel_n/oldlabel_n}.
How does the model ensure a.acquire
that the user that acquires {a,b}::RESOURCE
the resource is the one to 0 1
Process prefixing is useful for modeling shared resources: release it? a.acquire
Relabeling to ensure that composed
a.release
RESOURCE = (acquire->release->RESOURCE). b.release processes synchronize on particular actions.
b.acquire b.use a.use
USER = (acquire->use->release->USER). RESOURCE_SHARE
CLIENT = (call->wait->continue->CLIENT).
0 1 2 3 4
||RESOURCE_SHARE = (a:USER || b:USER SERVER = (request->service->reply->SERVER).
|| {a,b}::RESOURCE).
b.release
action relabeling action relabeling - prefix labels action hiding - abstraction to reduce complexity
release
Concurrency: concurrent execution 19 Concurrency: concurrent execution 20 Concurrency: concurrent execution 21
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
structure diagrams structure diagrams - resource sharing 3.2 Multi-threaded Programs in Java
Structure diagram for CLIENT_SERVER ? PRINTER_SHARE Concurrency in Java occurs when more than one thread is alive.
a:USER ThreadDemo has two threads which rotate displays.
CLIENT call request printer
call SERVER
printer:
continue reply service RESOURCE
wait reply
acquire
b:USER release
printer
Structure diagram for CLIENT_SERVERv2 ?
||PRINTER_SHARE
= (a:USER||b:USER||{a,b}::printer:RESOURCE).
Concurrency: concurrent execution 22 Concurrency: concurrent execution 23 Concurrency: concurrent execution 24
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
ThreadDemo model ThreadDemo implementation in Java - class diagram Rotator class
ThreadDemo creates two ThreadPanel displays when initialized.
THREAD_DEMO ThreadPanel manages the display and control buttons, and delegates calls to class Rotator implements Runnable {
a.run b.run rotate() to DisplayThread. Rotator implements the runnable interface.
a.pause b.pause
public void run() {
a:ROTATOR b:ROTATOR try {
a.rotate stop b.rotate Applet Panel
while(true) ThreadPanel.rotate();
GraphicCanvas
} catch(InterruptedException e) {}
A,B display }
ThreadDemo ThreadPanel
ROTATOR = PAUSED, }
Interpret init() rotate() thread Thread
PAUSED = (run->RUN | pause->PAUSED run, start()
start()
|interrupt->STOP), pause, stop() stop() Rotator implements the runnable interface, calling
RUN = (pause->PAUSED |{run,rotate}->RUN interrupt DisplayThread
ThreadPanel.rotate() to move the display.
|interrupt->STOP). as inputs, rotate()
rotate as Runnable run()finishes if an exception is raised by Thread.interrupt().
||THREAD_DEMO = (a:ROTATOR || b:ROTATOR)
/{stop/{a,b}.interrupt}. an output. target
Rotator
Concurrency: concurrent execution 25 Concurrency: concurrent execution run() 26 Concurrency: concurrent execution 27
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
ornamental garden Program - class diagram ornamental garden program Turnstile class
Applet Thread The Counter object and Turnstile threads are created by the class Turnstile extends Thread {
NumberCanvas display;
go() method of the Garden applet: Counter people; The run()
east,west people private void go() { Turnstile(NumberCanvas n,Counter c) method exits
Garden Turnstile Counter and the thread
counter = new Counter(counterD); { display = n; people = c; }
init() run() increment() terminates after
west = new Turnstile(westD,counter); public void run() { Garden.MAX
go()
east = new Turnstile(eastD,counter); try{ visitors have
eastD, display display west.start(); display.setvalue(0); entered.
westD, NumberCanvas east.start(); for (int i=1;i<=Garden.MAX;i++){
counterD Thread.sleep(500); //0.5 second between arrivals
setvalue() } display.setvalue(i);
people.increment();
The Turnstile thread simulates the periodic arrival of a visitor to
Note that counterD, westD and eastD are objects of }
the garden every second by sleeping for a second and then invoking NumberCanvas used in chapter 2. } catch (InterruptedException e) {}
the increment() method of the counter object. }
Concurrency: shared objects & mutual exclusion 4 Concurrency: shared objects & mutual exclusion 5 }
Concurrency: shared objects & mutual exclusion 6
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Counter class ornamental garden program - display concurrent method activation
ornamental garden Model ornamental garden model checking for errors - animation
go const N = 4
end
go GARDEN range T = 0..N The alphabet of Scenario checking
end
arrive set VarAlpha = { value.{read[T],write[T]} } process VAR is - use animation to
value
declared explicitly
east: value:VAR VAR = VAR[0], as a set constant, produce a trace.
TURNSTILE display
VAR[u:T] = (read[u] ->VAR[u]
read VarAlpha.
go |write[v:T]->VAR[v]).
end write
arrive value
TURNSTILE = (go -> RUN), The alphabet of Is this trace
RUN = (arrive-> INCREMENT TURNSTILE is
west: |end -> TURNSTILE), correct?
TURNSTILE extended with
INCREMENT = (value.read[x:T]
VarAlpha to ensure
Process VAR models read and write access to the shared -> value.write[x+1]->RUN
)+VarAlpha. no unintended free
counter value. actions in VAR ie. all
||GARDEN = (east:TURNSTILE || west:TURNSTILE actions in VAR must
Increment is modeled inside TURNSTILE since Java method || { east,west,display} ::value:VAR)
be controlled by a
activations are not atomic i.e. thread objects east and west /{ go /{ east,west} .go,
TURNSTILE.
may interleave their read and write actions. end/{ east,west} .end} .
Concurrency: shared objects & mutual exclusion 10 Concurrency: shared objects & mutual exclusion 11 Concurrency: shared objects & mutual exclusion 12
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
checking for errors - exhaustive analysis ornamental garden model - checking for errors Interference and Mutual Exclusion
Exhaustive checking - compose the model with a TEST ||TESTGARDEN = (GARDEN || TEST).
process which sums the arrivals and checks against the Use LTSA to perform an exhaustive search for ERROR. Destructive update, caused by the arbitrary
display value: interleaving of read and write actions, is termed
Trace to property violation in TEST:
TEST = TEST[0], go interference.
TEST[v:T] = east.arrive
(when (v<N){east.arrive,west.arrive}->TEST[v+1] east.value.read.0
|end->CHECK[v] west.arrive Interference bugs are extremely difficult to
), west.value.read.0 locate. The general solution is to give methods
CHECK[v:T] = Like STOP, ERROR is east.value.write.1 LTSA produces
(display.value.read[u:T] -> mutually exclusive access to shared objects.
a predefined FSP west.value.write.1 the shortest
(when (u==v) right -> TEST[v] local process (state), end path to reach
Mutual exclusion can be modeled as atomic
|when (u!=v) wrong -> ERROR numbered -1 in the display.value.read.1 ERROR. actions.
) equivalent LTS. wrong
)+{display.VarAlpha}.
Concurrency: shared objects & mutual exclusion 13 Concurrency: shared objects & mutual exclusion 14 Concurrency: shared objects & mutual exclusion 15
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
4.2 Mutual exclusion in Java mutual exclusion - the ornamental garden Java synchronized statement
Concurrent activations of a method in Java can be made Access to an object may also be made mutually exclusive by using the
synchronized statement:
mutually exclusive by prefixing the method with the keyword
synchronized. synchronized (object) { statements }
A less elegant way to correct the example would be to modify the
We correct COUNTER class by deriving a class from it and Turnstile.run() method:
making the increment method synchronized: synchronized(counter) {counter.increment();}
class SynchronizedCounter extends Counter {
SynchronizedCounter(NumberCanvas n) Why is this “less elegant”?
{super(n);} Java associates a lock with every object. The Java compiler inserts
synchronized void increment() { code to acquire the lock before executing the body of the
super.increment(); synchronized method and code to release the lock before the To ensure mutually exclusive access to an object,
} method returns. Concurrent threads are blocked until the lock is all object methods should be synchronized.
} released.
Concurrency: shared objects & mutual exclusion 16 Concurrency: shared objects & mutual exclusion 17 Concurrency: shared objects & mutual exclusion 18
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
4.3 Modeling mutual exclusion Revised ornamental garden model - checking for errors COUNTER: Abstraction using action hiding
To add locking to our model, define a LOCK, compose it with A sample animation
go To model shared objects
the shared VAR in the garden, and modify the alphabet set : east.arrive directly in terms of their
execution trace east.value.acquire const N = 4
synchronized methods, we
LOCK = (acquire->release->LOCK). east.value.read.0 range T = 0..N
can abstract the details by
||LOCKVAR = (LOCK || VAR). east.value.write.1 VAR = VAR[0], hiding.
set VarAlpha = {value.{read[T],write[T], east.value.release VAR[u:T] = ( read[u]->VAR[u]
west.arrive For SynchronizedCounter
acquire, release}} | write[v:T]->VAR[v]).
west.value.acquire we hide read, write,
Modify TURNSTILE to acquire and release the lock: west.value.read.1 LOCK = (acquire->release->LOCK). acquire, release actions.
TURNSTILE = (go -> RUN), west.value.write.2 INCREMENT = (acquire->read[x:T]
RUN = (arrive-> INCREMENT west.value.release -> (when (x<N) write[x+1]
|end -> TURNSTILE), end ->release->increment->INCREMENT
INCREMENT = (value.acquire display.value.read.2 )
-> value.read[x:T]->value.write[x+1] right )+{read[T],write[T]}.
-> value.release->RUN
)+VarAlpha. Use TEST and LTSA to perform an exhaustive check. ||COUNTER = (INCREMENT||LOCK||VAR)@{increment}.
Concurrency: shared objects & mutual exclusion 19 Concurrency: shared objects & mutual exclusion Is TEST satisfied? 20 Concurrency: shared objects & mutual exclusion 21
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Minimized Concepts
increment increment increment increment
LTS:
process interference
0 1 2 3 4
mutual exclusion
Concurrency: shared objects & mutual exclusion 22 Concurrency: shared objects & mutual exclusion 23
©Magee/Kramer ©Magee/Kramer
Chapter 5 monitors & condition synchronization 5.1 Condition synchronization
Practice: private data and synchronized methods (exclusion). A controller is required for a carpark, which only permits
wait(), notify() and notifyAll() for condition synch. cars to enter when the carpark is not full and does not
single thread active in the monitor at a time permit cars to leave when there are no cars in the carpark.
Car arrival and departure are simulated by separate threads.
Concurrency: monitors & condition synchronization 1 Concurrency: monitors & condition synchronization 2 Concurrency: monitors & condition synchronization 3
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
♦ Events or actions of interest? CARPARKCONTROL(N=4) = SPACES[N], ♦ Model - all entities are processes interacting by actions
SPACES[i:0..N] = (when(i>0) arrive->SPACES[i-1]
arrive and depart |when(i<N) depart->SPACES[i+1] ♦ Program - need to identify threads and monitors
♦ Identify processes. ). ♦thread - active entity which initiates (output) actions
arrivals, departures and carpark control ARRIVALS = (arrive->ARRIVALS). ♦monitor - passive entity which responds to (input) actions.
♦ Define each process and interactions (structure). DEPARTURES = (depart->DEPARTURES). For the carpark?
||CARPARK = CARPARK
CARPARK (ARRIVALS||CARPARKCONTROL(4)||DEPARTURES).
ARRIVALS arrive CARPARK depart DEPARTURES
ARRIVALS arrive CARPARK depart DEPARTURES CONTROL
CONTROL
Guarded actions are used to control arrive and depart.
LTS?
Concurrency: monitors & condition synchronization 4 Concurrency: monitors & condition synchronization 5 Concurrency: monitors & condition synchronization 6
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
carpark program - class diagram carpark program carpark program - Arrivals and Departures threads
Runnable Arrivals and Departures implement Runnable, class Arrivals implements Runnable {
Applet
CarParkControl provides the control (condition synchronization). CarParkControl carpark;
arrivals,
departures Arrivals(CarParkControl c) {carpark = c;}
CarPark ThreadPanel Arrivals carpark Instances of these are created by the start() method of the
CarPark applet : public void run() {
carDisplay try {
Departures while(true) { Similarly Departures
public void start() { which calls
ThreadPanel.rotate(330);
CarParkControl
CarParkControl c = carpark.arrive(); carpark.depart().
arrive() new DisplayCarPark(carDisplay,Places); ThreadPanel.rotate(30);
depart() arrivals.start(new Arrivals(c)); }
We have omitted departures.start(new Departures(c)); } catch (InterruptedException e){}
disp DisplayThread and } }
CarParkCanvas DisplayCarPark GraphicCanvas }
threads managed by
ThreadPanel.
How do we implement the control of CarParkControl?
Concurrency: monitors & condition synchronization 7 Concurrency: monitors & condition synchronization 8 Concurrency: monitors & condition synchronization 9
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Carpark program - CarParkControl monitor condition synchronization in Java condition synchronization in Java
class CarParkControl { Java provides a thread wait set per monitor (actually per object) We refer to a thread entering a monitor when it acquires the mutual
mutual exclusion with the following methods:
protected int spaces; by synch methods exclusion lock associated with the monitor and exiting the monitor
protected int capacity; public final void notify() when it releases the lock.
CarParkControl(int n) condition Wakes up a single thread that is waiting on this object's set. Wait() - causes the thread to exit the monitor,
{capacity = spaces = n;} synchronization? permitting other threads to enter the monitor.
public final void notifyAll()
synchronized void arrive() { Wakes up all threads that are waiting on this object's set.
block if full?
… --spaces; … Monitor
(spaces==0) public final void wait()
} Thread A Thread B
throws InterruptedException data
synchronized void depart() { block if empty? Waits to be notified by another thread. The waiting thread wait()
… ++spaces; … (spaces==N) releases the synchronization lock associated with the monitor. notify()
} When notified, the thread must wait to reacquire the monitor
} before resuming execution.
Concurrency: monitors & condition synchronization 10 Concurrency: monitors & condition synchronization 11 Concurrency: monitors & condition synchronization 12
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
condition synchronization in Java CarParkControl - condition synchronization models to monitors - summary
class CarParkControl {
FSP: when cond act -> NEWSTAT protected int spaces; Active entities (that initiate actions) are implemented as threads.
protected int capacity; Passive entities (that respond to actions) are implemented as monitors.
Java: public synchronized void act() CarParkControl(int n)
throws InterruptedException {capacity = spaces = n;} Each guarded action in the model of a monitor is
{ implemented as a synchronized method
synchronized void arrive() throws InterruptedException {
while (!cond) wait(); while (spaces==0) wait();
which uses a while loop and wait() to
// modify monitor data --spaces; implement the guard. The while loop condition is
notifyAll() notify(); the negation of the model guard condition.
}
}
synchronized void depart() throws InterruptedException {
The while loop is necessary to retest the condition cond to ensure that while (spaces==capacity) wait(); Changes in the state of the monitor are signaled to
cond is indeed satisfied when it re-enters the monitor. ++spaces; waiting threads using notify() or notifyAll().
notify();
notifyall() is necessary to awaken other thread(s) that may be Why is it safe to use notify()
}
waiting
Concurrency: to enter
monitors the monitor
& condition now that the monitor data has been changed.
synchronization 13
here rather than notifyAll()14?
}Concurrency: monitors & condition synchronization Concurrency: monitors & condition synchronization 15
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
bounded buffer - a data-independent model bounded buffer program - buffer monitor bounded buffer program - producer process
public interface Buffer {…}
We separate the class Producer implements Runnable {
BUFFER(N=5) = COUNT[0], class BufferImpl implements Buffer { interface to Buffer buf;
COUNT[i:0..N] … permit an String alphabet= "abcdefghijklmnopqrstuvwxyz";
= (when (i<N) put->COUNT[i+1] public synchronized void put(Object o) alternative Producer(Buffer b) {buf = b;}
throws InterruptedException { implementation
|when (i>0) get->COUNT[i-1] while (count==size) wait(); public void run() { Similarly Consumer
buf[in] = o; ++count; in=(in+1)%size; later. try { which calls buf.get().
).
notify(); int ai = 0;
} while(true) {
PRODUCER = (put->PRODUCER). public synchronized Object get() ThreadPanel.rotate(12);
CONSUMER = (get->CONSUMER). throws InterruptedException { buf.put(new Character(alphabet.charAt(ai)));
while (count==0) wait(); ai=(ai+1) % alphabet.length();
Object o =buf[out]; ThreadPanel.rotate(348);
||BOUNDEDBUFFER = buf[out]=null; --count; out=(out+1)%size; }
notify();
(PRODUCER||BUFFER(5)||CONSUMER). return (o); } catch (InterruptedException e){}
} }
}
}
Concurrency: monitors & condition synchronization 28 Concurrency: monitors & condition synchronization 29 Concurrency: monitors & condition synchronization 30
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
5.4 Nested Monitors nested monitors - bounded buffer program nested monitors - bounded buffer model
Suppose that, in place of using the count variable and condition synchronized public void put(Object o) const Max = 5
throws InterruptedException { range Int = 0..Max
synchronization directly, we instead use two semaphores full and empty.down();
empty to reflect the state of the buffer. buf[in] = o; SEMAPHORE ...as before...
++count; in=(in+1)%size;
class SemaBuffer implements Buffer { full.up(); BUFFER = (put -> empty.down ->full.up ->BUFFER
… } |get -> full.down ->empty.up ->BUFFER
Semaphore full; //counts number of items synchronized public Object get() ).
throws InterruptedException{
Semaphore empty; //counts number of spaces full.down(); PRODUCER = (put -> PRODUCER).
Object o =buf[out]; buf[out]=null; CONSUMER = (get -> CONSUMER).
SemaBuffer(int size) { --count; out=(out+1)%size;
this.size = size; buf = new Object[size]; empty.up(); Does this behave
||BOUNDEDBUFFER = (PRODUCER|| BUFFER || CONSUMER
full = new Semaphore(0); return (o); as desired? ||empty:SEMAPHORE(5)
empty= new Semaphore(size); }
||full:SEMAPHORE(0)
} empty is decremented during a put operation, which is blocked
… )@{put,get}. Does this behave
if empty is zero; full is decremented by a get operation, which
} as desired?
is blocked if full is zero.
Concurrency: monitors & condition synchronization 31 Concurrency: monitors & condition synchronization 32 Concurrency: monitors & condition synchronization 33
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
nested monitors - bounded buffer model nested monitors - revised bounded buffer program nested monitors - revised bounded buffer model
LTSA analysis predicts a possible DEADLOCK: The only way to avoid it in Java is by careful design. In this BUFFER = (put -> BUFFER
Composing example, the deadlock can be removed by ensuring that the monitor |get -> BUFFER
potential DEADLOCK lock for the buffer is not acquired until after semaphores are ).
States Composed: 28 Transitions: 32 in 60ms decremented.
Trace to DEADLOCK: PRODUCER =(empty.down->put->full.up->PRODUCER).
public void put(Object o) CONSUMER =(full.down->get->empty.up->CONSUMER).
get
throws InterruptedException {
The Consumer tries to get a character, but the buffer is empty.down(); The semaphore actions have been moved to the producer
empty. It blocks and releases the lock on the semaphore synchronized(this){ and consumer. This is exactly as in the implementation
full. The Producer tries to put a character into the buf[in] = o; ++count; in=(in+1)%size; where the semaphore actions are outside the monitor .
}
buffer, but also blocks. Why? Does this behave as desired?
full.up();
This situation is known as the nested monitor problem. } Minimized LTS?
Concurrency: monitors & condition synchronization 34 Concurrency: monitors & condition synchronization 35 Concurrency: monitors & condition synchronization 36
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
5.5 Monitor invariants Summary
An invariant for a monitor is an assertion concerning the variables
it encapsulates. This assertion must hold whenever there is no thread Concepts
executing inside the monitor i.e. on thread entry to and exit from a monitors: encapsulated data + access procedures
monitor . mutual exclusion + condition synchronization
CarParkControl Invariant: 0 ≤ spaces ≤ N
nested monitors
Semaphore Invariant: 0 ≤ value
Model
Buffer Invariant: 0 ≤ count ≤ size
and 0 ≤ in < size guarded actions
and 0 ≤ out< size Practice
and in = (out + count) modulo size
private data and synchronized methods in Java
Invariants can be helpful in reasoning about correctness of monitors wait(), notify() and notifyAll() for condition synchronization
using a logical proof-based approach. Generally we prefer to use a
single thread active in the monitor at a time
model-based approach amenable to mechanical checking .
Concurrency: monitors & condition synchronization 37 Concurrency: monitors & condition synchronization 38
©Magee/Kramer ©Magee/Kramer
Chapter 6 Deadlock Deadlock: four necessary and sufficient conditions
Wait-for cycle 6.1 Deadlock analysis - primitive processes deadlock analysis - parallel composition
♦ deadlocked state is one with no outgoing transitions ♦ in systems, deadlock may arise from the
Has A awaits B
parallel composition of interacting processes.
♦ in FSP: STOP process
A RESOURCE = (get->put->RESOURCE).
Has E awaits A MOVE = (north->(south->MOVE|north->STOP)). p:P
SYS
printer: P = (printer.get->scanner.get
printer RESOURCE ->copy
north north
E MOVE scanner
get
->printer.put->scanner.put
B Has B awaits C put
->P).
0 1 2
q:Q scanner:
Q = (scanner.get->printer.get
south printer RESOURCE ->copy
scanner get ->scanner.put->printer.put
D C ♦ animation to produce a trace. put
->Q).
||SYS = (p:P||q:Q
Has C awaits D ♦analysis using LTSA: Trace to DEADLOCK: Deadlock Trace? ||{p,q}::printer:RESOURCE
Has D awaits E north ||{p,q}::scanner:RESOURCE
(shortest trace to STOP) Avoidance?
north ).
Concurrency: Deadlock 4 Concurrency: Deadlock 5 Concurrency: Deadlock 6
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
deadlock analysis - avoidance 6.2 Dining Philosophers Dining Philosophers - model structure diagram
FORK = (get -> put -> FORK). Trace to DEADLOCK: This is the situation where
PHIL = (sitdown ->right.get->left.get phil.0.sitdown all the philosophers become Deadlock is easily
->eat ->right.put->left.put phil.0.right.get hungry at the same time, sit detected in our
->arise->PHIL). phil.1.sitdown down at the table and each model.
phil.1.right.get philosopher picks up the How easy is it to
phil.2.sitdown fork to his right. detect a potential
Table of philosophers:
phil.2.right.get deadlock in an
||DINERS(N=5)= forall [i:0..N-1] phil.3.sitdown The system can make no
further progress since each implementation?
(phil[i]:PHIL || phil.3.right.get
{phil[i].left,phil[((i-1)+N)%N].right}::FORK phil.4.sitdown philosopher is waiting for a
). phil.4.right.get fork held by his neighbor i.e.
a wait-for cycle exists!
Can this system deadlock?
Concurrency: Deadlock 10 Concurrency: Deadlock 11 Concurrency: Deadlock 12
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Dining Philosophers - implementation in Java Dining Philosophers - Fork monitor Dining Philosophers - Philosopher implementation
class Fork { class Philosopher extends Thread {
private boolean taken=false; taken ...
Applet Thread public void run() {
private PhilCanvas display; encodes the
try {
♦philosophers: private int identity; state of the while (true) { // thinking
1 n view active entities Fork(PhilCanvas disp, int id) fork view.setPhil(identity,view.THINKING);
Diners Philosopher { display = disp; identity = id;} sleep(controller.sleepTime()); // hungry
1 - implement as
display synchronized void put() { view.setPhil(identity,view.HUNGRY);
threads taken=false; right.get(); // gotright chopstick
n view.setPhil(identity,view.GOTRIGHT);
Fork display ♦forks: shared display.setFork(identity,taken);
notify(); sleep(500); Follows
passive entities } left.get(); // eating from the
- implement as view.setPhil(identity,view.EATING); model
synchronized void get() sleep(controller.eatTime()); (sitting
controller monitors throws java.lang.InterruptedException { right.put(); down and
PhilCanvas while (taken) wait(); left.put();
♦display taken=true; }
leaving the
table have
display.setFork(identity,taken); } catch (java.lang.InterruptedException e){} been
} }
Concurrency: Deadlock 13 Concurrency: Deadlock 14 Concurrency: Deadlock omitted).15
} }
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Safety & Liveness Concepts: properties: true for every possible execution A safety property asserts that nothing bad happens.
safety: nothing bad happens
♦ STOP or deadlocked state (no outgoing transitions)
Properties liveness: something good eventually happens
♦ ERROR process (-1) to detect erroneous behaviour
Models: safety: no reachable ERROR/STOP state command
♦ How can we specify that some action, disaster, LOOP = (mutex.down -> enter -> exit
never occurs? -> mutex.up -> LOOP).
||SEMADEMO = (p[1..3]:LOOP
||{p[1..3]}::mutex:SEMAPHORE(1)).
-1 0
Single Lane Bridge - model Single Lane Bridge - CARS model Single Lane Bridge - CONVOY model
Single Lane Bridge - implementation in Java Single Lane Bridge - BridgeCanvas Single Lane Bridge - RedCar
An instance of BridgeCanvas class is created by SingleLaneBridge class RedCar implements Runnable {
Applet Thread Runnable applet - ref is passed to each newly created RedCar and BlueCar object.
BridgeCanvas display; Bridge control; int id;
blue, class BridgeCanvas extends Canvas { RedCar(Bridge b, BridgeCanvas d, int id) {
red display display
Single RedCar BlueCar public void init(int ncars) {…} //set number of cars display = d; this.id = id; control = b;
Lane }
control control //move red car with the identity i a step
Bridge Bridge //returns true for the period from just before,until just after car on bridge public void run() {
public boolean moveRed(int i) try {
throws InterruptedException{…} while(true) {
Active entities (cars) are Safe while (!display.moveRed(id)); // not on bridge
//move blue car with the identity i a step control.redEnter(); // request access to bridge
implemented as threads. Bridge //returns true for the period from just before,until just after car on bridge while (display.moveRed(id)); // move over bridge
Passive entity (bridge) is public boolean moveBlue(int i) control.redExit(); // release access to bridge
throws InterruptedException{…} }
implemented as a monitor. BridgeCanvas
public synchronized void freeze(){…}// freeze display } catch (InterruptedException e) {}
BridgeCanvas enforces no public synchronized void thaw(){…} //unfreeze display }
overtaking. } }
Similarly for the BlueCar
Concurrency: safety & liveness properties 16 Concurrency: safety & liveness properties 17 Concurrency: safety & liveness properties 18
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Single Lane Bridge - class Bridge Single Lane Bridge Single Lane Bridge - SafeBridge
Single Lane Bridge - SafeBridge 7.3 Liveness Progress properties - fair choice
to wake up waiting threads only when the number of cars on the A progress property asserts that it is always the case that tails would be chosen
bridge is zero i.e. when the last car leaves the bridge. an action is eventually executed. Progress is the opposite of infinitely often. 0 1 2
But does every car eventually get an opportunity starvation, the name given to a concurrent programming
This requires Fair Choice !
to cross the bridge? This is a liveness property. situation in which an action is never executed. heads
Concurrency: safety & liveness properties 22 Concurrency: safety & liveness properties 23 Concurrency: safety & liveness properties 24
tails
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
Progress properties Progress properties Progress properties
pick
Suppose that there were two possible coins that could be
toss
progress P = {a1,a2..an} defines a progress picked up: pick
pick toss toss
property P which asserts that in an infinite execution of toss
a trick coin
a target system, at least one of the actions a1,a2..an pick toss toss
0 1 2 3 4 5
and a regular
will be executed infinitely often. 0 1 2 3 4 5
coin…… progress HEADS = {heads} heads tails
heads
heads tails
progress TAILS = {tails}
heads Progress violation: TAILS
COIN system: progress HEADS = {heads} ? TWOCOIN = (pick->COIN|pick->TRICK), LTSA check progress Path to terminal set of states:
progress TAILS = {tails} ? TRICK = (toss->heads->TRICK), pick
COIN = (toss->heads->COIN|toss->tails->COIN). Actions in terminal set:
{toss, heads}
LTSA check progress: No progress violations detected.
TWOCOIN: progress HEADS = {heads} ?
progress TAILS = {tails} ? progress HEADSorTails = {heads,tails} ?
Concurrency: safety & liveness properties 25 Concurrency: safety & liveness properties 26 Concurrency: safety & liveness properties 27
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
7.4 Congested single lane bridge congested single lane bridge model congested single lane bridge model
Progress - 2 nd revision of single lane bridge model Revised single lane bridge implementation - FairBridge Revised single lane bridge implementation - FairBridge
const True = 1 class FairBridge extends Bridge { synchronized void blueEnter(){
const False = 0
Analysis ? private int nred = 0; //count of red cars on the bridge throws InterruptedException {
private int nblue = 0; //count of blue cars on the bridge ++waitblue;
range B = False..True while (nred>0||(waitred>0 && !blueturn)) wait();
private int waitblue = 0; //count of waiting blue cars
/* bt - true indicates blue turn, false indicates red turn */ private int waitred = 0; //count of waiting red cars --waitblue;
BRIDGE = BRIDGE[0][0][0][0][True], private boolean blueturn = true; ++nblue;
} The “fair” check
BRIDGE[nr:T][nb:T][wr:T][wb:T][bt:B] = synchronized void redEnter() box must be
(red[ID].request -> BRIDGE[nr][nb][wr+1][wb][bt] throws InterruptedException { synchronized void blueExit(){ chosen in order to
|when (nb==0 && (wb==0||!bt)) ++waitred; --nblue; select the
while (nblue>0||(waitblue>0 && blueturn)) wait(); blueturn = false; FairBridge
red[ID].enter -> BRIDGE[nr+1][nb][wr-1][wb][bt] if (nblue==0) notifyAll();
--waitred; implementation.
|red[ID].exit -> BRIDGE[nr-1][nb][wr][wb][True] This is a direct }
++nred;
|blue[ID].request -> BRIDGE[nr][nb][wr][wb+1][bt] } translation from }
|when (nr==0 && (wr==0||bt))
synchronized void redExit(){ the model.
blue[ID].enter -> BRIDGE[nr][nb+1][wr][wb-1][bt] Note that we did not need to introduce a new request monitor method.
--nred; The existing enter methods can be modified to increment a wait count
|blue[ID].exit -> BRIDGE[nr][nb-1][wr][wb][False] blueturn = true;
if (nred==0)notifyAll(); before testing whether or not the caller can access the bridge.
).
Concurrency: safety & liveness properties 40 Concurrency:
} safety & liveness properties 41 Concurrency: safety & liveness properties 42
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
7.5 Readers and Writers readers/writers model readers/writers model - READER & WRITER
progress WRITE = {writer[1..Nwrite].acquireWrite} Progress violation: WRITE Writer We concentrate on the monitor implementation:
progress READ = {reader[1..Nread].acquireRead} Path to terminal set of states: starvation: interface ReadWrite {
reader.1.acquireRead The number public void acquireRead()
WRITE - eventually one of the writers will acquireWrite Actions in terminal set: of readers throws InterruptedException;
READ - eventually one of the readers will acquireRead {reader.1.acquireRead, reader.1.releaseRead, never drops public void releaseRead();
reader.2.acquireRead, reader.2.releaseRead} to zero. public void acquireWrite()
Adverse conditions using action priority? throws InterruptedException;
reader.1.acquireRead
we lower the priority of the release actions for both Try the public void releaseWrite();
readers and writers. Applet! }
reader.2.acquireRead
||RW_PROGRESS = READERS_WRITERS writer.1.acquireWrite
We define an interface that identifies the monitor
>>{reader[1..Nread].releaseRead,
writer[1..Nread].releaseWrite}.
writer.2.acquireWrite reader.1.acquireRead reader.2.releaseRead
methods that must be implemented, and develop a number
0 1 2 3 4 5
of alternative implementations of this interface.
Progress Analysis ? LTS? Firstly, the safe READWRITELOCK.
writer.2.releaseWrite reader.1.releaseRead reader.2.acquireRead
Concurrency: safety & liveness properties 49 Concurrency: safety & liveness properties
writer.1.releaseWrite 50 Concurrency: safety & liveness properties 51
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
a Cruise Control System - requirements a Cruise Control System - hardware model - outline design
When the car Parallel Interface Adapter (PIA) is polled every 100msec. It ♦outline processes and interactions.
ignition is switched records the actions of the sensors: • buttons (on, off, resume)
on and the on Sensor Scan monitors Cruise Controller triggers
buttons • brake (pressed)
button is pressed, the buttons, brake, clear speed and record
polled
the current speed brake • accelerator (pressed) accelerator and speed, and enables or
PIA Sensors
is recorded and the accelerator engine events. disables the speed control.
system is enabled: CPU • engine (on, off).
engine
it maintains the Engine Prompts
speed of the car at
the recorded wheel interrupt D/A throttle Input Speed monitors Speed Control clears and Throttle
setting. the speed when the records the speed, and sets the
engine is on, and sets the throttle actual
Pressing the brake, Wheel revolution sensor generates interrupts to enable the car provides the current accordingly when enabled. throttle.
accelerator or off speed to be calculated. speed readings to speed
setThrottle
button disables the speed control.
buttons system. Pressing Output: The cruise control system controls the car speed by setting
resume or on re- the throttle via the digital-to-analogue converter.
Concurrency: model-based design 4 Concurrency: model-based design 5 Concurrency: model-based design 6
enables the system.
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
model -design model - structure, actions and interactions model elaboration - process definitions
♦ Main events, actions and interactions. The CONTROL CRUISE SENSORSCAN = ({Sensors} -> SENSORSCAN).
CONTROL CONTROL // monitor speed when engine on
on, off, resume, brake, accelerator system is SENSOR Sensors INPUTSPEED = (engineOn -> CHECKSPEED),
Sensors CRUISE SYSTEM
engine on, engine off, structured SCAN CONTROLLER CHECKSPEED = (speed -> CHECKSPEED
speed, setThrottle as two |engineOff -> INPUTSPEED
processes. Engine Prompts ).
clearSpeed,recordSpeed,
Prompts The main // zoom when throttle set
enableControl,disableControl INPUT speed THROTTLE THROTTLE =(setThrottle -> zoom -> THROTTLE).
actions and SPEED set
♦ Identify main processes. interactions SPEED
CONTROL Throttle // perform speed control when enabled
are as SPEEDCONTROL = DISABLED,
Sensor Scan, Input Speed, shown. DISABLED =({speed,clearSpeed,recordSpeed}->DISABLED
Cruise Controller, Speed Control and | enableControl -> ENABLED
set Sensors = {engineOn,engineOff,on,off, ),
Throttle
resume,brake,accelerator} ENABLED = ( speed -> setThrottle -> ENABLED
♦ Identify main properties. set Engine = {engineOn,engineOff} |{recordSpeed,enableControl} -> ENABLED
set Prompts = {clearSpeed,recordSpeed, | disableControl -> DISABLED
safety - disabled when off, brake or accelerator pressed. ).
enableControl,disableControl}
♦Define and structure
Concurrency: model-based design each process. 7 Concurrency: model-based design 8 Concurrency: model-based design 9
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
model elaboration - process definitions model - CONTROL subsystem model - Safety properties
// enable speed control when cruising, ||CONTROL =(CRUISECONTROLLER Safety checks are compositional. If there is no violation
// disable when off, brake or accelerator pressed ||SPEEDCONTROL at a subsystem level, then there cannot be a violation
CRUISECONTROLLER = INACTIVE, ). when the subsystem is composed with other subsystems.
INACTIVE =(engineOn -> clearSpeed -> ACTIVE),
ACTIVE =(engineOff -> INACTIVE This is because, if the ERROR state of a particular safety
|on->recordSpeed->enableControl->CRUISING
Animate to check particular However, we need to property is unreachable in the LTS of the subsystem, it
), traces: - Is control enabled analyse to exhaustively remains unreachable in any subsequent parallel
CRUISING =(engineOff -> INACTIVE after the engine is check: Safety: Is the composition which includes the subsystem. Hence...
|{ off,brake,accelerator} switched on and the on control disabled
-> disableControl -> STANDBY button is pressed? when off, brake or Safety properties should be composed with the
|on->recordSpeed->enableControl->CRUISING - Is control disabled accelerator is
), when the brake is appropriate system or subsystem to which the
pressed?
STANDBY =(engineOff -> INACTIVE then pressed? Progress: Can every
property refers. In order that the property can check
|resume -> enableControl -> CRUISING - Is control re- action eventually be the actions in its alphabet, these actions must not be
|on->recordSpeed->enableControl->CRUISING enabled when resume selected? hidden in the system.
). is then pressed?
Concurrency: model-based design 10 Concurrency: model-based design 11 Concurrency: model-based design 12
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
model - Safety properties model analysis model - Progress properties
property CRUISESAFETY = We can now compose the whole system: Progress checks are not compositional. Even if there is no
({off,accelerator,brake,disableControl} -> CRUISESAFETY violation at a subsystem level, there may still be a
|{on,resume} -> SAFETYCHECK ||CONTROL = violation when the subsystem is composed with other
), (CRUISECONTROLLER||SPEEDCONTROL||CRUISESAFETY subsystems.
SAFETYCHECK = )@ {Sensors,speed,setThrottle}.
({on,resume} -> SAFETYCHECK This is because an action in the subsystem may satisfy
|{off,accelerator,brake} -> SAFETYACTION ||CRUISECONTROLSYSTEM = progress yet be unreachable when the subsystem is
|disableControl -> CRUISESAFETY (CONTROL||SENSORSCAN||INPUTSPEED||THROTTLE). composed with other subsystems which constrain its
), behavior. Hence...
SAFETYACTION =(disableControl->CRUISESAFETY).
LTS?
Deadlock? Progress checks should be conducted on the complete
||CONTROL =(CRUISECONTROLLER No deadlocks/errors
||SPEEDCONTROL Safety? target system after satisfactory completion of the
||CRUISESAFETY safety checks.
Is CRUISESAFETY
).
violated? Progress?
Concurrency: model-based design 13 Concurrency: model-based design 14 Concurrency: model-based design 15
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
model - Progress properties cruise control model - minimized LTS model - revised cruise control system
Check with no ||CRUISEMINIMIZED = (CRUISECONTROLSYSTEM) Modify CRUISECONTROLLER so that control is disabled when the
hidden actions engine is switched off:
Progress violation for actions: @ {Sensors,speed}.
…
{engineOn, clearSpeed, engineOff, on, recordSpeed, engineOff CRUISING =(engineOff -> disableControl -> INACTIVE
enableControl, off, disableControl, brake, accelerator |{ off,brake,accelerator} -> disableControl -> STANDBY
accelerator...........} brake
|on->recordSpeed->enableControl->CRUISING
engineOn on off engineOn
Path to terminal set of states: ),
engineOn …
clearSpeed
OK now?
0 1 2 3 4 5 Modify the safety property:
on speed on speed speed
recordSpeed speed
property IMPROVEDSAFETY = ({off,accelerator,brake,disableControl,
engineOff} -> IMPROVEDSAFETY
enableControl Control is not disabled |{on,resume} -> SAFETYCHECK
engineOff on
engineOff when the engine is resume Action hiding and minimization ),
engineOn switched off ! can help to reduce the size of SAFETYCHECK = ({on,resume} -> SAFETYCHECK
Actions in terminal set: the LTS diagram and make it |{off,accelerator,brake,engineOff} -> SAFETYACTION
{speed, setThrottle, zoom} easier to interpret. |disableControl -> IMPROVEDSAFETY
engineOff ),
Concurrency: model-based design 16 Concurrency: model-based design 17 Concurrency: model-based design
SAFETYACTION =(disableControl -> IMPROVEDSAFETY). 18
©Magee/Kramer ©Magee/Kramer ©Magee/Kramer
model - revised cruise control system model - system sensitivities model interpretation
The central role of design architecture 8.2 from models to implementations cruise control system - class diagram
Architecture
Design Applet
CarSpeed
architecture Model setThrottle()
getSpeed()
describes the
gross ♦ identify the main active entities dis p
CruiseControl
car
CarSimulator
organization - to be implemented as threads
and global control
Behavioural View Performance View Implementation View ♦ identify the main (shared) passive entities Controller Runnable
structure of
brake()
the system in - to be implemented as monitors accelerator() sc cs
SpeedControl
terms of its ♦ identify the interactive display environment engineOff()
constituent engineOn() enableControl() SpeedControl
components. Analysis Program Construction - to be implemented as associated classes on() disableControl() interacts with
off() recordSpeed() the car
♦ structure the classes as a class diagram resume() clearSpeed()
simulation via
We consider that the models for analysis and Java interface
dis p
the implementation should be considered as CruiseDisplay CarSpeed.
elaborated views of this basic design structure.
Concurrency: model-based design 22 Concurrency: model-based design 23 Concurrency: model-based design 24
©Magee/Kramer ©Magee/Kramer CRUISECONTROLLER SPEEDCONTROL
©Magee/Kramer
cruise control system - class Controller cruise control system - class Controller cruise control system - class SpeedControl
class Controller { synchronized void engineOn(){ class SpeedControl implements Runnable {
final static int INACTIVE = 0; // cruise controller states Controller if(controlState==INACTIVE) final static int DISABLED = 0; //speed control states SpeedControl
final static int ACTIVE = 1; {sc.clearSpeed(); controlState=ACTIVE;} final static int ENABLED = 1; is an active
final static int CRUISING = 2;
is a passive This is a private int state = DISABLED; //initial state
} entity - when
final static int STANDBY = 3; entity - it direct private int setSpeed = 0; //target speed
private int controlState = INACTIVE; //initial state synchronized void on(){ private Thread speedController; enabled, a new
reacts to if(controlState!=INACTIVE){ translation
private CarSpeed cs; //interface to control speed
private SpeedControl sc; from the thread is
events. sc.recordSpeed(); sc.enableControl(); private CruiseDisplay disp;
Controller(CarSpeed cs, CruiseDisplay disp) Hence we controlState=CRUISING; model. SpeedControl(CarSpeed cs, CruiseDisplay disp){ created which
{sc=new SpeedControl(cs,disp);} }
implement it } this.cs=cs; this.disp=disp; periodically
synchronized void brake(){ disp.disable(); disp.record(0); obtains car
if (controlState==CRUISING ) as a monitor synchronized void off(){ }
{sc.disableControl(); controlState=STANDBY; } if(controlState==CRUISING ) speed and sets
synchronized void recordSpeed(){
} {sc.disableControl(); controlState=STANDBY;} setSpeed=cs.getSpeed(); disp.record(setSpeed); the throttle.
synchronized void accelerator(){ } }
if (controlState==CRUISING ) synchronized void resume(){ synchronized void clearSpeed(){
{sc.disableControl(); controlState=STANDBY; } if(controlState==STANDBY) if (state==DISABLED) {setSpeed=0;disp.record(setSpeed);}
} {sc.enableControl(); controlState=CRUISING;} }
synchronized void engineOff(){ }
if(controlState!=INACTIVE) { } synchronized void enableControl(){
if (controlState==CRUISING) sc.disableControl(); if (state==DISABLED) {
controlState=INACTIVE; disp.enable(); speedController= new Thread(this);
}
Concurrency: model-based design 25 Concurrency: model-based design 26 Concurrency:speedController.start();
model-based design state=ENABLED; 27
} ©Magee/Kramer ©Magee/Kramer
} ©Magee/Kramer
}
synchronous message passing - applet Java implementation - channel Java implementation - sender
selective receive Java implementation - selective receive Java implementation - selective receive
public void run() {
CARPARK class MsgCarPark implements Runnable {
try {
private Channel arrive,depart;
ARRIVALS arrive CARPARK depart DEPARTURES Select sel = new Select();
CONTROL private int spaces,N;
sel.add(depart);
private StringCanvas disp;
sel.add(arrive);
while(true) {
public MsgCarPark(Channel a, Channel l,
CARPARKCONTROL(N=4) = SPACES[N], ThreadPanel.rotate(12);
StringCanvas d,int capacity) {
SPACES[i:0..N] = (when(i>0) arrive->SPACES[i-1] arrive.guard(spaces>0);
depart=l; arrive=a; N=spaces=capacity; disp=d;
depart.guard(spaces<N);
|when(i<N) depart->SPACES[i+1] }
switch (sel.choose()) {
). … Implement case 1:depart.receive();display(++spaces);
public void run() {…} CARPARKCONTROL as a
ARRIVALS = (arrive->ARRIVALS). break;
Implementation } thread MsgCarPark
DEPARTURES = (depart->DEPARTURES). case 2:arrive.receive();display(--spaces);
using message which receives signals break;
||CARPARK = (ARRIVALS||CARPARKCONTROL(4) passing? from channels arrive }
||DEPARTURES). and depart. } See
} catch InterrruptedException{} Applet
Concurrency: message passing 10 Concurrency: message passing 11 Concurrency: message passing 12
©Magee/Kramer ©Magee/Kramer } ©Magee/Kramer
10.2 Asynchronous Message Passing - port asynchronous message passing - applet Java implementation - port
♦ res=call(e,req) - send the ♦ req=accept(e) - receive Two clients call a Entries are implemented as list
Select Selectable
server which services a extensions of ports, add() guard()
value req as a request the value of the request request at a time. thereby supporting queuing choose()
message which is queued to message from the entry e and selective receipt.
Channel Port
the entry e. into local variable req. The send() send()
calling process is blocked if The call method creates a
receive() receive()
Java implementation - entry model of entry and applet rendezvous Vs monitor method invocation
public class Entry extends Port { We reuse the models for ports and channels …
private CallMsg cm; What is the difference?
public Object call(Object req) throws InterruptedException { EntryDemo … from the point of view of the client?
Channel clientChan = new Channel();
send(new CallMsg(req,clientChan)); CLIENT() entry:ENTRY SERVER
return clientChan.receive();
… from the point of view of the server?
} entry.call[M] entry.accept
… mutual exclusion?
public Object accept()throws InterruptedException {
cm = (CallMsg) receive();
return cm.request; set M = {replyA,replyB} // reply channels
}
||ENTRY = PORT/{call/send, accept/receive}.
Which implementation is more efficient?
public void reply(Object res) throws InterruptedException {
cm.replychan.send(res); … in a local context (client and server in same computer)?
CLIENT(CH='reply) = (entry.call[CH]->[CH]->CLIENT).
}
SERVER = (entry.accept[ch:M]->[ch]->SERVER). … in a distributed context (in different computers)?
private class CallMsg { Action labels
Object request; Channel replychan;
CallMsg(Object m, Channel c) ||EntryDemo = (CLIENT('replyA)||CLIENT('replyB) used in
expressions or
Do call, accept and || entry:ENTRY || SERVER ).
{request=m; replychan=c;} as parameter
} reply need to be values must be
Concurrency:
} message passing synchronized methods?
22 Concurrency: message passing prefixed23with Concurrency: message passing 24
©Magee/Kramer a©Magee/Kramer
single quote. ©Magee/Kramer
Summary Course Outline
Concepts ♦ Processes and Threads
synchronous message passing – channel
asynchronous message passing – port
♦ Concurrent Execution
- send and receive / selective receive ♦ Shared Objects & Interference
Concepts
rendezvous bidirectional comms - entry
- call and accept ... reply
♦ Monitors & Condition Synchronization Models
Models ♦ Deadlock Practice
channel : relabelling, choice & guards ♦ Safety and Liveness Properties
port : message queue, choice & guards
entry : port & channel ♦ Model-based Design
Practice ♦ Dynamic systems ♦Concurrent Software Architectures
distributed computing (disjoint memory)
♦ Message Passing ♦Timed Systems
threads and monitors (shared memory)
Concurrency: message passing 25 Concurrency: message passing 26
©Magee/Kramer ©Magee/Kramer
This is highlighted when LTSA is performing a computation, which could potentially take a long time such
LTSA User Manual as minimisation. Clicking on the Stop button will abort the activity.
www.doc.ic.ac.uk/~jnm/book/firstbook/ltsa/ltsa-doc/User- Target
manual.html The target choice box is used to select the composite process to be analysed. If there is only one composite
process then this is set automatically. If no composite process is specified then the target displays
User manual "DEFAULT" which is the composite process consisting of the composition of all primitive processes in the
current specification. For a specification with multiple composite processes, it is necessary to initialise the
target choice when a specification is first loaded by invoking Parse from the Build menu.
It is the hope of the designers of LTSA that this manual should be largely unnecessary. In most cases, the
user simply has to enter a specification in the FSP window and invoke one of the analysis functions from the
Check menu. LTSA will perform the necessary compilation and LTS composition.
Contents
LTSA Window
LTSA Window
The LTSA window has the following controls in addition to the menubar.
Edit Button
This brings the FSP window to the front. The FSP window is used to enter the FSP specification text to be
analysed. Text can be loaded from file (using the File menu) if LTSA is running as an application or it may
be pasted into the window if LTSA is running as an applet.
LTS construction - Build
Results Button
Brings the Output window to the front. This displays the results of analysis, error messages etc. This menu contains all the functions necessary to generate an LTS from an FSP description. However,
usually, it is not necessary to invoke these functions directly. For example, compilation is implicitly invoked
Stop Button if the description is changed between successive calls to the safety check function.
Parse
1/7 2/7
Performs a syntax check on the text in the FSP window. The location of the first error detected is Run
highlighted and an error message displayed in the output window. Consequently, errors are located and
fixed one at a time. Performs a user-controlled animation of the target composite process. Uses the component LTSs rather than
the composite LTS, so larger systems can be animated even if they cannot be exhaustively checked.
After a successful parse, the target choice will contain the list of composite processes. The visible process is DEFAULT is the alphabet of the target composite process and allows explicit contol of all actions. This
the target for compilation etc. In addition, the list of actions menu's available from Check/Run is updated. may be reduced by declaring an explicit menu e.g.
Generates an LTS for each of the component processes (whether primitive or composite) of the target The current state of each component LTS displayed in a Draw window is updated by the animator. By
composite process. After compilation, the component processes may be viewed either graphically or default, the Animator window includes Run and Step buttons. These are used to control actions which are
textually - see Window. Compile will automatically invoke parse if the FSP window has been changed since not in the action menu and consequently do not have click boxes. These buttons do not appear if the autorun
the last Compile (or Parse). However, if a new target or action menu is added, Parse must be invoked option is selected in the Options menu. The Run button permits a sequence of actions to occur where
explicitly to update the target and run lists these actions are not explicitly controlled. The Step button permits a single such action to occur.
Compose
Generates a single LTS by composing the component LTSs produced by compile for a specified target.
After composition, the LTS may be viewed graphically or textually. Error messages produced during
composition indicate safety property violations and deadlocks.
Minimise
Minimises the LTS produced by composition according to Milner's observation equivalence relation.
Reachable
Analysis functions - Check Performs an "on-the-fly" depth first search on the set of component LTS for the target. Since the composite
LTS is not required, this uses less storage than Safety. Property violations and deadlocks are detected,
however, no counter examples (traces) are produced.
The analysis functions operate on the target composite process indicated in the Target choice box. If this
has not been compiled or composed, compilation and composition are automatically invoked.
Safety
Performs a breadth first search on the target LTS. If a property violation or deadlock is found, the shortest Display functions - Window
trace of actions that would lead to the property violation or deadlock is displayed in the output window.
Progress Alphabet
Computes the connected components for the target LTS. Checks for progress violations with respect to the Displays the action alphabet for either the component process of a target or the target LTS itself. The
declared progress properties. If no progress properties are declared then a check with respect to a default alphabet is by default displayed concisely - actions with common prefixes are collected into sets or ranges.
property is performed. The default property has all the actions in the alphabet of the current target. The alphabet may also be viewed in an expanded form by choosing Expanded from the View menu. The
3/7 4/7
view can be adjusted between fully expanded and the concise view using Expand and Contract from
View.
Text
Displays as text the LTS for either the component process of a target or the target LTS itself. When LTSA is
running as an application, the textual representation may be saved to file.
A separate window for the process is created when the process is selected from the Draw menu. When
LTSA is running as an application, the graphical representation may be saved to file (in PICT format) from
this window. The Freeze Drawing while adjusting Window option under the File menu allows the LTS
graph to be repositioned inside the window before the PICT image is saved.
Draw
Displays graphically the LTS for either the component process of a target or the target LTS itself. A button
Options
for each process in the target appears at the left of the window. Clicking on the process button displays the
LTS for that process. During animation the process buttons for each process participating in the last action
to occur are coloured red.
Display warning messages
5/7 6/7
Displays a warning message when an undefined state is mapped to the ERROR state during compilation.
Default is set.
Halts compilation with an error message when an undefined state is found. Default is not set.
If set, composite processes are minimised by default during compilation (ie. Composite processes which are
components of the target). Default is not set.
Use large font in all windows. Useful for demonstrations and presentations. Default is not set.
Transitions are always drawn clockwise, consequently, arrows are not strictly necessary. The LTS will
sometimes be clearer without arrows. Default is set.
Displays the process name for an LTS in the Draw window. Defaults is not set.
Removes Run and Step buttons from Animator window. Actions are selected until an action in the menu
set is enabled. Default is not set.
7/7
FSP Quick Reference Guide A.2 Composite Processes
http://www.doc.ic.ac.uk/~jnm/book/ltsa/Appendix-A-2e.html A composite process is the parallel composition of one or more processes. The definition of a composite
process is preceded by ||.
Appendix A Example
||Composite = (P || Q).
FSP Quick Reference
Parallel If P and Q are processes then (P||Q) represents the
Composition || concurrent execution of P and Q.
A.1 Processes Replicator forall [i:1..N] P(i) is the parallel composition (P(1) ||
forall … || P(N))
A process is defined by a one or more local processes separated by commas. The definition is terminated by Process a:P prefixes each label in the alphabet of P with a.
a full stop. STOP and ERROR are primitive local processes. Labeling :
Process {a1,..,ax}::P replaces every label n in the
Example Sharing :: alphabet of P with the labels a1.n,…,ax.n. Further,
every transition (n->Q) in the definition of P is
Process = (a -> Local), replaced with the transitions ({a1.n,…,ax.n}->Q).
Priority High ||C =(P||Q)<<{a1,…,an} specifies a
Local = (b -> STOP). << composition in which the actions a1,…,an have
higher priority than any other action in the alphabet
Action Prefix - If x is an action and P a process then (x->P) of P||Q including the silent action tau. In any
> describes a process that initially engages in the choice in this system which has one or more of the
action x and then behaves exactly as described by P. actions a1,…,an labeling a transition, the
Choice | If x and y are actions then (x->P|y->Q) transitions labeled with lower priority actions are
describes a process which initially engages in either discarded.
of the actions x or y. After the first action has Priority Low >> ||C=(P||Q)>>{a1,…,an} specifies a
occurred, the subsequent behavior is described by P composition in which the actions a1,…,an have
if the first action was x and Q if the first action was lower priority than any other action in the alphabet
y. of P||Q including the silent action tau. In any
Guarded Action The choice (when B x -> P | y -> Q) choice in this system which has one or more
when means that when the guard B is true then the actions transitions not labeled by a1,…,an, the transitions
x and y are both eligible to be chosen, otherwise if B labeled by a1,…,an are discarded.
is false then the action x cannot be chosen.
Alphabet The alphabet of a process is the set of actions in Table A.2 – Composite Process Operators
Extension + which it can engage. P + S extends the alphabet of
the process P with the actions in the set S.
1/4 2/4
A.3 Common Operators A.5 FLTL – Fluent Linear Temporal Logic
The operators in Table A.3 may be used in the definition of both processes and composite processes. Fluent fluent FL = <{s1,…sn}, {e1..en}>
fluent initially B defines a fluent FL that is
Conditional The process if B then P else Q behaves as the initially true if the expression B is true and initially
if then process P if the condition B is true otherwise it false if the expression B is false. FL becomes true
else behaves as Q. If the else Q is omitted and B is false, immediately any of the initiating actions
then the process behaves as STOP. {s1,…sn}occur and false immediately any of the
Re-labeling / Re-labeling is applied to a process to change the terminating actions {e1..en} occur. If the term
names of action labels. The general form of re- initially B is omitted then FL is initially
labeling is: false.
/{newlabel_1/oldlabel_1,… Assertion assert PF = FLTL_Expression defines an
newlabel_n/oldlabel_n}. assert FLTL property.
Hiding \ When applied to a process P, the hiding operator
\{a1..ax} removes the action names a1..ax from the && conjunction (and)
alphabet of P and makes these concealed actions
"silent". These silent actions are labeled tau. Silent || disjunction (or)
actions in different processes are not shared. ! negation (not)
Interface @ When applied to a process P, the interface operator
@{a1..ax} hides all actions in the alphabet of P not -> implication ((A->B)≡ (!A || B))
labeled in the set a1..ax.
<-> equivalence ((A<->B) ≡(A->B)&&(B->A))
Table A.3 – Common Process Operators next time X F iff F holds in the next instant.
Safety A safety property P defines a deterministic until P U Q iff Q holds at some point in the future and P holds
property process that asserts that any trace including actions until then.
in the alphabet of P, is accepted by P.
Progress progress P = {a1,a2..an} defines a weak until P W iff P holds indefinitely or P U Q
Q
progress progress property P which asserts that in an infinite
execution of a target system, at least one of the forall forall [i:R] FL(i) conjunction of FL(i)
actions a1,a2..an will be executed infinitely often.
exists exists [i:R] FL(i) disjunction of FL(i)
Table A.4 – Safety and Progress Properties
3/4 4/4