introduction to computer science and programming in java concurrency issues.pdf · outline...

16
Concurrency Fundamentals of Computer Science http://csunplugged.org/routing-and-deadlock

Upload: others

Post on 22-Mar-2020

20 views

Category:

Documents


0 download

TRANSCRIPT

Page 2: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Outline

Multi-threaded programs

Multiple simultaneous paths of execution

Seemingly at once (single core)

Actually at the same time (multiple cores)

Concurrency issues

The dark side of threading

Unpredictability of thread scheduler

Protecting shared data:

synchronized methods

Deadlock

The really dark side of threading

Page 3: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

public class BlastOff implements Runnable { public void run() { for (int i = 10; i > 0; i--) System.out.print(i + " "); System.out.println("BLAST OFF!"); } }

public class Launch { public static void main(String [] args) { System.out.println("prepare for launch"); Thread thread = new Thread(new BlastOff()); thread.start(); System.out.println("done with launch"); } }

% java Launch prepare for launch done with launch 10 9 8 7 6 5 4 3 2 1 BLAST OFF!

Review: Creating & Starting a Thread

% java Launch prepare for launch 10 9 done with launch 8 7 6 5 4 3 2 1 BLAST OFF!

% java Launch prepare for launch 10 done with launch 9 8 7 6 5 4 3 2 1 BLAST OFF!

Page 4: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

% java ParallelSearch 1000000 2 7 16 42 99 Starting workers... Count of 2 = 9888 Count of 7 = 10222 Count of 16 = 9989 Count of 42 = 10099 Count of 99 = 9894

Review: Multithreading for Speed

Goal: Count how often different integers occur

In a large array of integers

Randomly generated in [0, 100)

Have one thread handle each target integer

Page 5: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

public class SearchWorker implements Runnable { private int target = 0; private int [] data = null; private int result = 0;

public SearchWorker(int target, int [] data) { this.target = target; this.data = data; }

public int getResult() { return result; }

public int getTarget() { return target; }

public void run() { for (int i = 0; i < data.length; i++) { if (data[i] == target) result++; } } }

Worker object: One of these is created for each target integer we want to search for.

Needs to keep track of its input: what number to search for, the array to search in.

Must remember its output: count of the target in the array.

Page 6: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

... final int DATA_SIZE = Integer.parseInt(args[0]); final int WORKERS = args.length - 1;

int [] data = new int[DATA_SIZE]; for (int i = 0; i < DATA_SIZE; i++) data[i] = (int) (Math.random() * 100);

SearchWorker [] workers = new SearchWorker[WORKERS]; Thread [] threads = new Thread[WORKERS];

for (int i = 0; i < WORKERS; i++) { workers[i] = new SearchWorker(Integer.parseInt(args[i + 1]), data); threads[i] = new Thread(workers[i]); threads[i].start(); }

for (int i = 0; i < WORKERS; i++) { try { threads[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Count of %d = %d\n", workers[i].getTarget(), workers[i].getResult()); } ...

Client program: 1. Parses command line arguments. 2. Creates random array of data to search

in. 3. Creates each worker, launches each

worker in its own thread. 4. Waits for each thread to finish, printing

out the worker’s result.

Page 7: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Trouble in Concurrency City: Act 1

Lost update problem Multiple threads

All sharing a single counter object

Each thread increments fixed number of times

public class Count { private int count = 0; public int getCount() { return count; } public void increment() { count++; } }

public class IncrementWorker implements Runnable { private Count count = null; public IncrementWorker(Count count) { this.count = count; } public void run() { for (int i = 0; i < 1000; i++) count.increment(); } }

Page 8: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Lost Update Problem

... Count count = new Count(); Thread [] threads = new Thread[N]; for (int i = 0; i < N; i++) { threads[i] = new Thread(new IncrementWorker(count)); threads[i].start(); } for (int i = 0; i < N; i++) { try { threads[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Final count = " + count.getCount()); ...

% java Increment 1 Final count = 1000 % java Increment 2 Final count = 2000 % java Increment 20 Final count = 20000 % java Increment 20 Final count = 19761 % java Increment 20 Final count = 19014

Page 9: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Synchronizing Methods

Only allow 1 worker in increment at a time!

Tell Java this using synchronized keyword

public class Count { private int count = 0; public int getCount() { return count; } public synchronized void increment() { count++; } }

% java Increment 20 Final count = 20000 % java Increment 20 Final count = 20000 % java Increment 20 Final count = 20000

Page 10: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Locking an Object

Each object instance has a lock

Multiple methods can be marked synchronized

Only one can be executing at any time

Locking is on the object level

On the instance of the class, not the class data type itself

Locking and unlocking takes time

Only synchronize methods if necessary

public void run() { for (int i = 0; i < 1000; i++) { synchronized (count) { count.increment(); } } }

Another approach to fixing the lost update problem.

Synchronization can be enforced on a block of code instead of an entire method.

Page 11: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Trouble in Concurrency City: Act 2

Concurrent access to same data structure

Many built-in containers are not thread-safe!

e.g. ArrayList, HashMap

Program will crash (probably)

Protect all reading/writing to shared structure

Via synchronized method or synchronized code block

Page 12: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

public class ArrayListBad implements Runnable { private static ArrayList<Integer> list = new ArrayList<Integer>();

public void run() { for (int i = 0; i < 10; i++) { list.add((int) (Math.random() * 100)); } System.out.println("Thread all done..."); }

public static void main(String[] args) { Thread t1 = new Thread(new ArrayListBad()); t1.start();

Thread t2 = new Thread(new ArrayListBad()); t2.start();

try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Phew, we made it!"); } } 12

May sometimes work, especially if loop in run() is short.

But most likely you’ll get some sort of exception: Exception in thread "Thread-1" Thread all done... java.lang.ArrayIndexOutOfBoundsException: 15 at java.util.ArrayList.add(Unknown Source) at ArrayListBad.run(ArrayListBad.java:12) at java.lang.Thread.run(Unknown Source) Phew, we made it!

Page 13: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

public class ArrayListGood implements Runnable { private static ArrayList<Integer> list = new ArrayList<Integer>(); public void run() { for (int i = 0; i < 100000; i++) { synchronized(list) { list.add((int) (Math.random() * 100)); } } System.out.println("Thread all done..."); } ...

13

Adding synchronized block protects the shared static list instance variable, now only one thread is allowed to add to the list at any point in time.

Page 14: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Trouble in Concurrency City: Act 3

Deadlock Program stops doing anything useful

All you need is 2 objects and 2 threads

Page 15: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Summary

Multi-threaded programs

Multiple simultaneous paths of execution

Seemingly at once (single core)

Actually at the same time (multiple cores)

Concurrency issues

The dark side of threading

Unpredictability of thread scheduler

Protecting shared data:

synchronized methods

Deadlock

The really dark side of threading

Page 16: Introduction to Computer Science and Programming in Java Concurrency Issues.pdf · Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single

Your Turn

Goal: Increment/decrement all ints in an array Create class NumHolder that implements Runnable, holds array of 100 ints

Create increment() and decrement() methods Methods that go through all 100 integers and ++ or -- them

Create run() method Loop 1000 times, each loop flip coin and call either increment() or decrement()

Create main program in NumHolderLaunch Create a single NumHolder object Create two threads, passing them the NumHolder object you created Print out NumHolder object Start threads, wait for them to finish Print out NumHolder again

Hint: All numbers should be the same in the second print of NumHolder

Open Moodle, go to CSCI 136, Section 01 Open the dropbox Activity 7 - Concurrency Drag and drop your program file to the Moodle dropbox You get: 1 point if you turn in something, 2 points if you turn in

something that is correct.