Title: Concurrency/synchronization using UML state models and sequence models: A brief review
1Concurrency/synchronization using UML state
models and sequence models A brief review
- April 21st, 2008
- Michigan State University
2Simple monitor-process pattern
Monitor process
/ reply (op, result )
Idle
guard / accept-call ( op(parms) )
Operation body
3Bounded Buffer Example
BoundedBuffer
Pulling
queue_.size ! 0 / accept-call ( pull )
do/ rv queue_.pull
/ reply ( pull, rv )
/ reply ( push )
queue_.size ! MAX / accept-call ( push(x) )
Pushing
do/ queue_.push(x)
4Example Code for Bufferpush
queue_.size() ! MAX / accept-call (push(x))
Idle
- void Bufferpush(int x)
-
- lock_.acquire()
- while (queue_.size() MAX)
- full_.wait()
-
- queue_.push(x)
- empty_.signal()
- lock_.release()
/ reply (push)
Pushing
do/ queue_.push(x)
5Example Code for Bufferpush
queue_.size() ! MAX / accept-call (push(x))
Idle
- void Bufferpush(int x)
-
- lock_.acquire()
- while (queue_.size() MAX)
- full_.wait()
-
- queue_.push(x)
- empty_.signal()
- lock_.release()
/ reply (push)
Pushing
do/ queue_.push(x)
6Example Code for Bufferpush
queue_.size() ! MAX / accept-call (push(x))
Idle
- void Bufferpush(int x)
-
- lock_.acquire()
- while (queue_.size() MAX)
- full_.wait()
-
- queue_.push(x)
- empty_.signal()
- lock_.release()
/ reply (push)
Pushing
do/ queue_.push(x)
7Example Code for Bufferpush
queue_.size() ! MAX / accept-call (push(x))
Idle
- void Bufferpush(int x)
-
- lock_.acquire()
- while (queue_.size() MAX)
- full_.wait()
-
- queue_.push(x)
- empty_.signal()
- lock_.release()
/ reply (push)
Pushing
do/ queue_.push(x)
8Example Code for Bufferpull
queue_.size() ! 0 / accept-call (pull)
Idle
- int Bufferpull()
-
- lock_.acquire()
- while (queue_.size() 0)
- empty_.wait()
-
- int rv queue_.pull()
- full_.signal()
- lock_.release()
- return rv
/ reply (pull, rv)
Pushing
do/ rv queue_.pull()
9More complex guard conditions
- Consider a banking application that allows
multiple clients to deposit and withdraw funds
from shared accounts - Goals
- Protect against data races, so that money is not
accidentally created or destroyed - Prevent overdrafts by making withdraw requests
block if account has insufficient funds - Question How should we model the behavior of an
account object?
10Monitor-process model of BankAccount
BankAccount
Depositing
/ accept-call ( deposit(amount) )
do/ balance_ amount
/ reply ( deposit )
/ reply ( withdraw )
Withdrawing
amount lt balance_ / accept-call (
withdraw(amount) )
do/ balance_ - amount
11Code for BankAccountwithdraw
amount lt balance_ / accept-call
(withdraw(amount))
Idle
- void
- BankAccountwithdraw(int amount)
-
- lock_.acquire()
- while (amount gt balance_)
- okToWithdraw_.wait()
-
- balance_ - amount
- lock_.release()
/ reply (withdraw)
Withdrawing
do/ balance_ - amount
12Code for BankAccountdeposit
/ accept-call (deposit(amount))
Idle
- void
- BankAccountdeposit(int amount)
-
- lock_.acquire()
- balance_ amount
- okToWithdraw_.broadcast()
- lock_.release()
/ reply (deposit)
Depositing
do/ balance_ amount
13Signal vs. Broadcast
- When one thread changes the value of a condition
upon which others might be waiting, the modifier
is obliged to notify these waiting threads - Always safest, though perhaps not very efficient,
to use broadcast to notify waiting threads after
a change - Question When is it safe to use signal?
14Mixed Monitor objects
- Some methods on a monitor class may be
non-monitor methods - Do not acquire / release mutex lock
- Multiple threads may access simultaneously
- Threads may access non-monitor methods while 1
thread in a monitor method - 1 thread may enter monitor method while other
threads in non-monitor method
15(No Transcript)