Concurrency Concepts
Concurrency
Concepts of Concurrency
Concurrency occurs at multiple levels:
Machine instruction level
High-level language statement level
Unit level
Program level
Concurrency is more realistic and can be more efficient, but it carries unique, fundamental complexities.
Traditionally studied in the context of operating systems.
Concurrency Example
Client-server application such as web browsing.
Web browser rendering a page.
Page is a shared resource.
Thread for each image load, text rendering, and user input (e.g., Stop button).
These threads cannot all write to the page simultaneously.
Timeline of Multiprocessor Architectures
Late 1950s: One general-purpose processor and one or more special-purpose processors for input and output operations.
Early 1960s: Multiple complete processors, used for program-level concurrency.
Mid-1960s: Multiple partial processors, used for instruction-level concurrency.
Single-Instruction Multiple-Data (SIMD) machines.
Multiple-Instruction Multiple-Data (MIMD) machines.
A primary focus is shared memory MIMD machines (multiprocessors).
Categories of Concurrency
Physical concurrency:
Multiple independent processors (multiple threads of control).
Logical concurrency:
The appearance of physical concurrency is presented by time-sharing one processor.
Software can be designed as if there were multiple threads of control.
Co-routines (quasi-concurrency) have a single thread of control.
A thread of control in a program is the sequence of program points reached as control flows through the program.
Motivations for the Use of Concurrency
Multiprocessor computers capable of physical concurrency are now widely used.
Even if a machine has just one processor, a program written to use concurrent execution can be faster than the same program written for nonconcurrent execution.
Involves a different way of designing software that can be very useful; many real-world situations involve concurrency.
Many program applications are now spread over multiple machines, either locally or over a network.
Concurrency Concepts - Definitions
Multiprogramming: Several programs loaded into memory and executed in an interleaved manner.
Scheduler: Switches from one program or thread to another.
Time-sharing: Allows multiple users to communicate with a computer simultaneously.
Process: An execution context, including registers, activation stack, next instruction to be executed, etc.
Concurrent program: A program designed to have two or more execution contexts; also known as multithreaded, since more than one execution context can be active simultaneously.
Parallel program: Two or more threads simultaneously active.
Distributed program: Designed so that different pieces are on computers connected by a network.
Concurrency: A program with multiple, active threads.
Tasks
Definition: A task (or process or thread) is a program unit that can be in concurrent execution with other program units.
Tasks differ from ordinary subprograms in that:
A task may be implicitly started.
When a program unit starts the execution of a task, it is not necessarily suspended.
When a task’s execution is completed, control may not return to the caller.
Tasks usually work together.
Heavyweight tasks execute in their own address space.
Lightweight tasks all run in the same address space (more efficient).
A task is disjoint if it does not communicate with or affect the execution of any other task in the program in any way.
Task Synchronization
A mechanism that controls the order in which tasks execute.
Two kinds of synchronization:
Cooperation synchronization
Competition synchronization
Task communication is necessary for synchronization, provided by:
Shared nonlocal variables
Parameters
Message passing
Kinds of Synchronization
Cooperation: Task A must wait for task B to complete some specific activity before task A can continue its execution (e.g., the producer-consumer problem).
Competition: Two or more tasks must use some resource that cannot be simultaneously used (e.g., a shared counter).
Competition is usually provided by mutually exclusive access (approaches are discussed later).
Need for Competition Synchronization
Example:
Task A:
TOTAL = TOTAL + 1Task B:
TOTAL = 2 * TOTALDepending on the order of execution, there could be four different results.
Scheduler
Providing synchronization requires a mechanism for delaying task execution.
Task execution control is maintained by a program called the scheduler, which maps task execution onto available processors.
States of a Thread
Created (New): but not yet ready to run.
Runnable (Ready): ready to run; awaiting a processor.
Running: executing.
Blocked: waiting on some resource.
Terminated (Dead): stopped; no longer active in any sense.
Threads
Inter-thread communication needs to occur:
Thread requires exclusive access to some resource.
Thread needs to exchange data with another thread.
Can communicate via:
Shared variables
Message passing
Parameters
Race Condition
Definition: A race condition occurs when the resulting value of a variable depends on the execution order of two or more threads.
Example:
c = c + 1Machine level:
load cadd 1store c
If
cinitially 0:With 2 threads, can get 1 or 2.
With n threads, can get 1, 2, …, n.
Deadlock
Definition: A deadlock occurs when a thread is waiting for an event that will never happen.
Necessary conditions for a deadlock to exist:
Threads claim exclusive access to resources.
Threads hold some resources while waiting for others.
Resources may not be removed from waiting threads (preemption).
A circular chain of threads exists in which each thread holds a resource needed by the next thread in the chain.
Design Issues for Concurrency
Competition and cooperation synchronization
Controlling task scheduling
How can an application influence task scheduling
How and when tasks start and end execution
How and when are tasks created
Methods of Providing Synchronization
Semaphores: Data structure used for controlling access, by multiple processes, to a common resource.
Monitors: Abstract data type to encapsulate the shared data and its operations in order to restrict access.
Semaphores
Definition: A semaphore is a data structure consisting of a counter and a queue for storing task descriptors.
A task descriptor is a data structure that stores all of the relevant information about the execution state of the task
Originally defined by Dijkstra in 1968.
Operations:
P(s)– ifs > 0thens--else enqueue threadV(s)– if a thread is enqueued then dequeue it elses++Binary semaphore
Counting semaphore
Concurrent Pascal Example
program SimpleProducerConsumer;
var
buffer : string;
full : semaphore = 0;
empty : semaphore = 1;
...
begin
cobegin
Producer;
Consumer;
coend;
end.
Concurrent Pascal Producer Example
procedure Producer;
var
tmp : string
begin
while (true) do
begin
produce(tmp);
{
begin critical section
}
tmp;
{
end critical section
}
P(empty);
buffer := V(full);
end;
end;
Concurrent Pascal Consumer Example
procedure Consumer;
var
tmp : string
begin
while (true) do
begin
P(full);
{
begin critical section
}
tmp := buffer;
V(empty);
{
end critical section
}
consume(tmp);
end;
end;
Concurrent Pascal ProducerConsumer Example
program ProducerConsumer;
const
size = 5;
var
buffer : array[1..size] of string;
inn : integer = 0;
out : integer = 0;
lock : semaphore = 1;
nonfull : semaphore = size;
nonempty : semaphore = 0;
...
Concurrent Pascal Producer
procedure Producer;
var
tmp : string
begin
while (true) do
begin
produce(tmp);
P(nonfull);
P(lock);
{
begin critical section
}
inn := inn mod size + 1;
buffer[inn] := tmp;
V(lock);
{
end critical section
}
V(nonempty);
end;
end;
Concurrent Pascal Consumer
procedure Consumer;
var
tmp : string
begin
while (true) do
begin
P(nonempty);
P(lock);
{
begin critical section
}
out := out mod size + 1;
tmp := buffer[out];
V(lock);
{
end critical section
}
V(nonfull);
consume(tmp);
end;
end;
Evaluation of Semaphores
Misuse of semaphores can cause failures in cooperation synchronization (e.g., the buffer can overflow).
Misuse of semaphores can cause failures in competition synchronization (e.g., the program can deadlock if the release is left out).
Monitors
Encapsulates a shared resource together with access functions.
Used in Ada, Java, C#
Locking is automatic.
Monitor implementation guarantees synchronized access by allowing only one access at a time.
Calls to monitor procedures are implicitly queued if the monitor is busy at the time of the call
Condition – thread queue signal wait
Concurrent Pascal Monitor Example
monitor Buffer;
const
size = 5;
var
buffer : array[1..size] of string;
in : integer = 0;
out : integer = 0;
count : integer = 0;
nonfull : condition;
nonempty : condition;
Concurrent Pascal Put Procedure
procedure put(s : string);
begin
if (count = size) then wait(nonfull);
in := in mod size + 1;
buffer[in] := tmp;
count := count + 1;
signal(nonempty);
end;
Concurrent Pascal Get Function
function get : string;
var
tmp : string
begin
if (count = 0) then wait(nonempty);
out := out mod size + 1;
tmp := buffer[out];
count := count - 1;
signal(nonfull);
get := tmp;
end;
Java Threads
The concurrent units in Java are methods named
runA
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();
Controlling Thread Execution
The
Threadclass has several methods to control the execution of threadsThe
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
States of a Java Thread
Diagram showing transitions between Created, Runnable, Running, Blocked, and Terminated states.
Java Example: Bouncing Balls
State of a ball in motion:
Location: , coordinates
Direction and velocity: ,
Size in pixels
Color
Ball methods:
Constructor
move: one step (delta)paint
Java Ball Example
public class Ball {
Color color = Color.red;
int x;
int y;
int diameter = 10;
int dx = 3;
int dy = 6;
Java Ball Example (Constructor)
public Ball (int ix, int iy) {
super();
x = ix;
y = iy;
color = new Color((x+y) % 256, x % 256, y % 256);
dx = x % 10 + 1;
dy = y % 10 + 1;
}
Java Ball Example (move method)
public void move () {
if (x < 0 || x >= BouncingBalls.width) dx = - dx;
if (y < 0 || y >= BouncingBalls.height) dy = - dy;
x += dx;
y += dy;
}
public void paint (Graphics g) {
g.setColor(color);
g.fillOval(x, y, diameter, diameter);
}
Java Ball Example (BouncingBalls class)
public class BouncingBalls extends JPanel {
public final static int width = 500;
public final static int height = 400;
private static Ball ball = new Ball(128, 127);
private Vector<Ball> list = new Vector();
Java Ball Example (BouncingBalls constructor)
public BouncingBalls ( ) {
setPreferredSize(new Dimension(width, height));
list.add(ball);
addMouseListener(new MouseHandler());
BallThread bt = new BallThread();
bt.start( );
}
Java Ball Example (MouseHandler class)
private class MouseHandler extends MouseAdapter {
public void mousePressed(MouseEvent e) {
Ball b = new Ball(e.getX(), e.getY());
list.add(b);
}
// mousePressed
} // MouseHandler
Java Ball Example (BallThread class)
private class BallThread extends Thread {
public boolean cont;
public void run( ) {
cont = true;
while (cont) {
for (Ball b : list) {
b.move();
}
repaint( );
try {
Thread.sleep(50);
} catch (InterruptedException exc) { }
}
}
}
Java Ball Example (paintChildren method)
public synchronized void
paintChildren(Graphics g) {
for (Ball b: list) {
b.paint(g);
}
}
Java Ball Example (main method)
public static void main(String[] args) {
JFrame frame = new JFrame("Bouncing Balls");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add( new BouncingBalls( ));
frame.setLocation(50, 50);
frame.pack();
frame.setVisible(true);
}
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
SleepA thread can be terminated with
Abort
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 integer
The
lockstatement:Used to mark a critical section of code in a thread:
lock (expression){...}
The
Monitorclass:Provides four methods that can be used to provide more sophisticated synchronization
C#’s Concurrency Evaluation
An advance over Java threads, e.g., any method can run its own thread
Thread termination is cleaner than in Java
Synchronization is more sophisticated
Summary
Concurrent execution can be at the instruction, statement, or subprogram level
Physical concurrency: when multiple processors are used to execute concurrent units
Logical concurrency: concurrent united are executed on a single processor
Two primary facilities to support subprogram concurrency: competition synchronization and cooperation synchronization
Mechanisms: semaphores, monitors, rendezvous, threads
High-Performance Fortran provides statements for specifying how data is to be distributed over the memory units connected to multiple processors