Concurrent Programming

 

COMMENTED VERSION

Lecturer: Prof. O. Nierstrasz
Schützenmattstr. 14/103, Tel. 631.4618

Secr.: Frau I. Huber, Tel. 631.4692

Assistants: M. Lumpe

WWW: http://iamwww.unibe.ch/~scg/Lectures/

 

Text:

Other Sources:

Tentative Schedule

 

Overview

 

safety, liveness, nondeterminism ...

 

  • Approach
idioms, patterns and architectural styles

 

  • Java and concurrency

Concurrency and Parallelism

 

"A sequential program specifies sequential execution of a list of statements; its execution is called a process. A concurrent program specifies two or more sequential programs that may be executed concurrently as parallel processes."

 

A concurrent program can be executed by:

Multiprogramming: processes share one or more processors
  1. Multiprocessing : each process runs on its own processor
    but with shared memory
  2. Distributed processing: each process runs on its own processor
    connected by a network to others
  3.  

    Assume only that all processes make positive finite progress.

    NB: Sometimes we distinguish between a process, which has its own address space provided by the operating system, and a thread, which shares an address space with other threads. Thus, a process may be multi-threaded. Here we consider threads and processes to be the same thing ...

Applications of Concurrency

 

There are many good reasons to build concurrent programs:

 

minimize response delay; maximize throughput

 

  • Real-time programming
process control applications

 

  • Simulation
modelling real-world concurrency

 

  • Parallelism
exploit multiple CPUs for number-crunching; exploit parallel algorithms

 

  • Distribution
coordinate distributed services

Limitations

 

But concurrent applications introduce complexity:

 

synchronization mechanisms are needed to maintain consistency

 

  • Liveness
special techniques may be needed to guarantee progress

 

  • Nondeterminism
debugging is harder because results may depend on "race conditions"

 

  • Communication complexity
communicating with a thread is more complex than a method call

 

  • Run-time overhead
thread construction, context switching and synchronization take time

Atomicity

 

Programs P1 and P2 execute concurrently:

 

{ x = 0 }

P1: x := x+1

P2: x := x+2

{ x = ? } May be 1, 2 or 3

 

What are possible values of x after P1 and P2 complete?

What is the intended final value of x?

 

Synchronization mechanisms are needed to restrict the possible interleavings of processes so that sets of actions can be seen as atomic.

Mutual exclusion ensures that statements within a critical section are treated atomically.

Safety and Liveness

 

There are two principal difficulties in implementing concurrent programs:

 

Safety -- ensuring consistency: -- AKA "nothing bad happens"

Mutual exclusion -- shared resources must be updated atomically
Condition synchronization -- operations may need to be delayed if shared resources are not in an appropriate state (e.g., read from empty buffer)

Liveness -- ensuring progress: -- AKA "something good happens"

No Deadlock -- some process can always access a shared resource
No Starvation -- all processes can eventually access shared resources

 

Notations for expressing concurrent computation must address:

Process Creation: how is concurrent execution specified?
  1. Communication: how do processes communicate?
  2. Synchronization: how is consistency maintained?
  3. NB: communication and synchronization are closely linked: shared variables vs. message-passing ...

Idioms, Patterns and Architectural Styles

 

Idioms, patterns and architectural styles express best practice in resolving common design problems.

 

"a low-level pattern specific to a programming language"
-- or more generally: "an implementation technique"

Examples: function objects, orthodox canonical form, futures, RPC

  • Design patterns
"a commonly-recurring structure of communicating components that solves a general design problem within a particular context"

Examples: Observer, Proxy, Master/Slave

  • Architectural patterns (styles)
"a fundamental structural organization schema for software systems"

Examples: dataflow (pipes and filters), blackboard, implicit invocation

-- cf. Buschmann et al., Pattern-Oriented Software Architecture, pp. 12-14

Although we use Java to illustrate techniques, we focus on generate solutions, not Java-specific idioms

Java

 

Language design influenced by existing OO languages (C++, Smalltalk ...):

Java applications do not have to be installed and maintained by users

Threads

A Thread defines its behaviour in its run method, but is started by calling start() :

// Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.

class TwoThreadsTest {
public static void main (String[] args) {
new SimpleThread("Jamaica").start(); // Instantiate, then start
new SimpleThread("Fiji").start();
}
}

class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str); // Call Thread constructor
}
public void run() { // What the thread does
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) { }
}
System.out.println("DONE! " + getName());
}
}

Running the TwoThreadsTest

java.lang.Thread

The Thread class encapsulates all information concerning running threads of control:

public class java.lang.Thread
extends java.lang.Object implements java.lang.Runnable
{
public Thread(); // Public constructors
public Thread(Runnable target);
public Thread(Runnable target, String name);
public Thread(String name);
...

public static void sleep(long millis) // Current thread sleeps
throws InterruptedException;
public static void yield(); // Yield control (equal priority)
...

public final String getName();
public void run(); // "main()" method
public synchronized void start(); // Starts a thread running
public final void suspend(); // Temporarily halts a thread
public final void resume(); // Allow to resume after suspend()
public final void stop(); // Throws a ThreadDeath error
public final void join() // Waits for thread to die
throws InterruptedException;
...
}

Transitions between Thread States

Runnable Æ
¨ Not Runnable

sleep()

time elapsed

suspend()

resume()

wait()

notify()