38 - Concurrency#
Ada’s Support for Concurrency#
The Ada 83 Message-Passing Model
Ada tasks have specification and body parts; the spec has the interface, which is the collection of entry points:
task Task_Example is
entry ENTRY_1 (Item : in Integer);
end Task_Example;
Task Body#
The body task describes the action that takes place when a rendezvous occurs.
A task that sends a message is suspended while waiting for the message to be accepted and during the rendezvous.
Entry points in the spec are described with accept clauses in the body:
accept entry_name (formal parameters) do
...
end entry_name;
Example#
task body Task_Example is
begin
loop
accept Entry_1 (Item: in Integer) do
...
end Entry_1;
end Entry_1;
end loop;
end Task_Example;
Message Passing#
Semantics:
The task executes to the top of the
acceptclause and waits for a messageDuring execution of the
acceptclause, the sender is suspended.acceptparameters can transmit information in either or both directions.Every
acceptclause has an associated queue to store waiting messages.
Rendezvous Time Lines:
Server/Actor Tasks#
A task that has
acceptclauses, but no other code is called a server task (the example above is a server task)A task without
acceptclauses is called an actor taskAn actor task can send messages to other tasks
Note: A sender must know the
entryname of the receiver, but not vice versa (assymmetric)
Graphical Representation of a Rendezvous#
Multiple Entry Points#
Tasks can have more than one entry point
The task specification has an
entryclause for eachThe task body has an
acceptclause for eachentryclause, placed in aselectclause, which is in a loop
task body Teller is
loop
select
accept Drive_Up(formal params) do
...
end Drive_Up;
...
or
accept Walk_Up(formal params) do
...
end Walk_Up;
...
end select;
end loop';
end Teller;
Semantics of tasks with multiple accept clauses#
If exactly one
entryqueue is nonempty, choose a message from itIf more than one
entryqueue is nonempty, choose one, nondeterministically, from which to accept a messageIf all are empty, wait
The construct is often called a selective wait
Extended
acceptclause - code following the clause, but before the next clauseExecuted concurrently with the caller
Cooperation Synchronization with Message Passing#
This is provided by Guarded accept clauses:
when not Full(Buffer) =>
accept Deposit (New_Value) do
...
end
An accept clause with a when clause is either open or closed.
A clause whose guard is true is called open
A clause whose guard is false is called closed
A clause without a guard is always open
Semantics of select with guarded accept clauses:
selectfirst checks the guards on all clausesIf exactly one is open, its queue is checked for messages
If more than one are open, non-deterministically choose a queue among them to check for messages
If all are closed, it is a runtime error
A
selectclause can include anelseclause to avoid the errorWhen the
elseclause completes, the loop repeats
Competition Synchronization with Message Passing#
Modeling mutually exclusive access to shared data
Example: a shared buffer
Encapsulate the buffer and its operations in a task
Competition synchronization is implicit in the semantics of
acceptclausesOnly one
acceptclause in a task can be active at any given time
Producer/Consumer Tasks#
task body Producer is
New_Value : Integer;
begin
loop
-- Produce New_Value –
Buf_Task.Deposit(New_Value);
end loop;
end Producer;
task body Consumer is
Stored_Value : Integer;
begin
loop
Buf_Task.Fetch(Stored_Value);
-- consume Stored_Value –
end loop;
end Consumer;
Protected Objects in Ada 95#
Protected objects: A more efficient way of implementing shared data to allow access to a shared data structure to be done without rendezvous.
A protected object is like a monitor
Access to a protected object is either through messages passed to entries, as with a task, or through protected subprograms
A protected procedure provides mutually exclusive read-write access to protected objects
A protected function provides concurrent read-only access to protected objects
Evaluation#
Message passing model of concurrency is powerful and general
Protected objects are a better way to provide synchronized shared data
In the absence of distributed processors, the choice between monitors (i.e., protected objects) and tasks with message passing is somewhat a matter of taste
For distributed systems, message passing is a better model for concurrency
Java Threads#
The concurrent units in Java are methods named run
A
runmethod code can be in concurrent execution with other such methodsThe process in which the
runmethods execute is called a thread
class myThread extends Thread {
public void run() { ... }
}
Thread myTh = new myThread();
myTh.start();
The Thread class has several methods to control the execution of threads
The
yieldis a request from the running thread to voluntarily surrender the processorThe
sleepmethod can be used by the caller of the method to block the threadThe
joinmethod is used to force a method to delay its execution until the run method of another thread has completed its execution
Thread Priorities#
A thread’s default priority is the same as the thread that creates it
If
maincreates a thread, its default priority isNORM_PRIORITY
Threads defined two other priority constants,
MAX_PRIORITYandMIN_PRIORITYThe priority of threads can be changed with the methods
setPriority
Competition Synchronization#
A method that includes the synchronized modifier disallows any other synchronized method from running on the object while it is in execution
...
public synchronized void deposit (int i) { ... }
public synchronized int fetch() { ... }
...
The above two methods are synchronized, which prevents them from interfering with each other.
If only a part of a method must be run without interference, it can be synchronized through
synchronized statement
synchronized (expression) {
statement
}
Cooperation Synchronization#
Cooperation synchronization in Java is achieved via
wait,notify, andnotifyAllmethodsAll methods are defined in
Object, which is the root class in Java, so all objects inherit them
The
waitmethod must be called in a loopThe
notifymethod is called to tell one waiting thread that the event it was waiting for has happenedThe
notifyAllmethod awakens all of the threads on the object’s wait list
Evaluation#
Java’s support for concurrency is relatively simple, but effective. However, it is not as powerful as Ada’s tasks.
C# Threads#
Loosely based on Java, but there are significant differences
Basic thread operations
Any method can run in its own thread
A thread is created by creating a
ThreadobjectCreating a thread does not start its concurrent execution; it must be requested through the
StartmethodA thread can be made to wait for another thread to finish with
JoinA thread can be suspended with
Sleep
Synchronizing Threads#
Three ways to synchronize C# threads:
The
Interlockedclass: Used when the only operations that need to be synchronized are incrementing or decrementing of an integerThe
lockstatement: Used to mark a critical section of code in a thread:lock(object) { /* the critical section */}The
Monitorclass: Provides five methods (Enter,Wait,Pause,Pause All,Exit) that can be used to provide more sophisticated syncronization
Evaluation#
An advance over Java threads, e.g., any method can run its own thread
Synchronization is more sophisticated