
Preliminary question. What is a program?
some operations may depend out the outcomes of other operations, others may be independent:
a1 = b1 + c1;
a2 = b2 - c2;
p = a1 * a2
A thread is a sequence of operations—think subprogram
Goal. Partition a program into multiple (logically indpendent) threads.
Payoff. Different threads can be executed in parallel (on parallel computer architecture)
Challenges.
Steps to writing a multithreaded program
Runnable object
Runnable interfacevoid run()
run() defines what your thread should doThread instance initialized with an instance of your Runnable objectA thread that increments a counter a bunch of times.
Runnable Objectpublic class CounterThread implements Runnable {
private Counter counter; private long times;
public CounterThread (Counter counter, long times) {
this.counter = counter; this.times = times;
}
public void run () {
for (long i = 0; i < times; i++) {
counter.increment();
}
}
}
public class Counter {
private long count = 0;
// return the current counter value
public long getCount () { return count; }
// increment the counter
public void increment () { ++count; }
// reset the counter value to 0
public void reset () { count = 0; }
}
Step 2. Create a Thread instance initialized with an instance of your Runnable object
Step 3. Start the thread
Step 4. (optional) Wait for the thread to complete
CounterExample.java
CounterExample with NUM_THREADS set to 1. What happens?CounterExample with NUM_THREADS set to 2.
NUM_THREADS set to 4, 8, 16, 1000, 1000…What happened with final counts as number of threads increased?
What happend with running times?
Why did this behavior occur?
Computer has two main components
CPU Capabilities:
Memory stores:
Random Access Machine (RAM) model interactions:
Counter object is stored in memory
Counter stores a value count
CountThread instructions stored in memoryWhen CounterThread is executed, it follows these instructions
for (long i = 0; i < times; i++) {
counter.increment();
}
In turn:
public void increment () { ++count; }
What are CPU/Memory interactions when counter.increment() is executed?
public void increment () { ++count; }
Modern computers:
increment operation on different coresincrement same Counter concurrentlySuppose: count = 7 & two threads both call increment() concurrently
What are the possible outcomes? What are results of different read/write operations?
Parallel Random Access Machine (PRAM)
read(i) and write(i, val)
read/write operations are atomic
Nondeterminism:
if multiple threads access same memory location simultaneously all “consistent” outcomes are possible
two processes call write(i, a) and write(i, b)
one process calls read(i) another write(i, a)
Consider: How could we avoid the CounterExample weirdness (nondeterminacy) and get a correct count with multiple threads?
More on nondeterminacy!