27 Concurrency
27 Concurrency
Introduction to Concurrency
reading: Grossman
1
Example program
• Suppose we have a program that reads several files and counts the
total number of unique words in all the files combined.
How can we modify the program to run in parallel using threads?
public class WordCounts {
public static void main(String[] args)
throws FileNotFoundException {
Set<String> words = new HashSet<String>();
long startTime = System.currentTimeMillis();
String[] files = {"bible", "abe", "hamlet", "tomsawyer"};
for (String filename : files) {
readFile(filename, words);
}
long endTime = System.currentTimeMillis();
long elapsed = endTime - startTime;
System.out.println("There are " + words.size()
+ " unique words.");
System.out.println("Took " + elapsed + " ms.");
}
...
2
Example program
• Suppose we have a program that reads several files and counts the
total number of unique words in all the files combined.
How can we modify the program to run in parallel using threads?
...
public static void readFile(String file, Set<String> words)
throws FileNotFoundException {
System.out.println("Starting to read " + file + " ...");
Scanner input = new Scanner(new File(file + ".txt"));
while (input.hasNext()) {
String word = input.next();
words.add(word);
}
System.out.println("Done reading " + file + ".");
}
}
3
Thread safety
• thread safe: Able to be used concurrently by multiple threads.
Many of the Java library classes are not thread safe!
In other words, if two threads access the same object, things break.
• Examples:
ArrayList and other collections from java.util are not thread
safe; two threads changing the same list at once may break it.
StringBuilder is not thread safe.
Java GUIs are not thread safe; if two threads are modifying a GUI
simultaneously, they may put the GUI into an invalid state.
• Counterexamples:
The Random class chooses numbers in a thread-safe way.
Some input/output (like System.out) is thread safe.
4
Parallel vs. concurrent
• parallel: Using multiple processing resources
work
(CPUs, cores) at once to solve a problem faster.
Example: A sorting algorithm that has several
threads each sort part of the array. CPUs/cores
5
Concurrency
• Unlike parallelism, not always about running faster.
Even a single-CPU, single-core machine may want concurrency.
• Useful for:
App responsiveness
• Example: Respond to GUI events in one thread while another thread is
performing an expensive computation
Processor utilization (mask I/O latency)
• If 1 thread is stuck working, others have something else to do
Failure isolation
• Convenient structure if want to interleave multiple tasks and do not want
an exception in one to stop the other
6
Time slicing
• If a given piece of code is run by two threads at once:
The order of which thread gets to run first is unpredictable.
How many statements of one thread run before the other thread runs
some of its own statements is unpredictable.
// Thread 1 // Thread 2
public void foo() { public void foo() {
... statement1;
statement1; ...
Time
statement2; ...
... statement2;
statement3; ...
} statement3;
}
7
Thread-unsafe code
• How can the following class be Scenario that breaks it:
broken by multiple threads?
• Threads A and B start.
1 public class Counter {
2 private int c = 0; • A calls increment and runs to the
end of line 4. It retrieves the old
3 public void increment() {
4 int old = c; value of 0.
5 c = old + 1; // c++; • B calls decrement and runs to the
6 }
end of line 8. It retrieves the old
7 public void decrement() { value of 0.
8 int old = c;
9 c = old - 1; // c--;
• A sets c to its old (0) + 1.
10 } • B sets c to its old (0) - 1.
11 public int value() {
12 return c; • The final value() is -1, though
13 } after one increment and one
14 }
decrement, it should be 0!
8
Synchronized blocks
// synchronized block:
// uses the given object as a lock
synchronized (object) {
statement(s);
}
9
Synchronized methods
// synchronized method: locks on "this" object
public synchronized type name(parameters) { ... }
10
Synchronized counter
public class Counter {
private int c = 0;
public synchronized void increment() {
int old = c;
c = old + 1; // c++;
}
public synchronized void decrement() {
int old = c;
c = old - 1; // c--;
}
public int value() {
return c;
}
}
The program is better than the previous one, but not much speed-up is
seen from the multiple threads. Why not?
14
Synchronized collections
• Java provides thread-safe collection wrappers via static methods in
the Collections class:
Method
Collections.synchronizedCollection(coll)
Collections.synchronizedList(list)
Collections.synchronizedMap(map)
Collections.synchronizedSet(set)
11 24 7 49
Example: 54
• lock bucket 4
• still okay to read bucket 7
14
16
Fine-grained locking
// keep a lock for each bucket
...
// Thread 1: add(42); ...
public void add(E value) { ...
int h = hash(value); // 2 ...
Node n = new Node(value); ...
... // Thread 2: add(72);
... public void add(E value) {
... int h = hash(value); // 2
... Node n = new Node(value);
Time
17
Concurrent collections
• New package java.util.concurrent contains collections that
are optimized to be safe for use by multiple threads:
class ConcurrentHashMap<K, V> implements Map<K, V>
class ConcurrentLinkedDeque<E> implements Deque<E>
class ConcurrentSkipListSet<E> implements Set<E>
class CopyOnWriteArrayList<E> implements List<E>
18
Object lock methods
• Every Java object has a built-in internal "lock".
A thread can "wait" on an object's lock, causing it to pause.
Another thread can "notify" on an object's lock, unpausing any other
thread(s) that are currently waiting on that lock.
An implementation of monitors, a classic concurrency construct.
method description
notify() unblocks one random thread waiting on this object's lock
notifyAll() unblocks all threads waiting on this object's lock
wait() causes the current thread to wait (block) on this object's
wait(ms) lock, indefinitely or for a given # of ms
These methods are not often used directly; but they are used
internally by other concurrency constructs (see next slide).
19
The volatile keyword
private volatile type name;
20
Deadlock
• liveness: Ability for a multithreaded program to run promptly.
21
New classes for locking
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
Class/interface description
Lock an interface for controlling access to a shared resource
ReentrantLock a class that implements Lock
ReadWriteLock like Lock but separates read operations from writes
Condition a particular shared resource that can be waited upon;
conditions are acquired by asking for one from a Lock