Concurrency http://csunplugged.org/routing-and-deadlock - - PowerPoint PPT Presentation

concurrency
SMART_READER_LITE
LIVE PREVIEW

Concurrency http://csunplugged.org/routing-and-deadlock - - PowerPoint PPT Presentation

Concurrency http://csunplugged.org/routing-and-deadlock Fundamentals of Computer Science Outline Multi-threaded programs Multiple simultaneous paths of execution Seemingly at once (single core) Actually at the same time (multiple


slide-1
SLIDE 1

Concurrency

Fundamentals of Computer Science

http://csunplugged.org/routing-and-deadlock

slide-2
SLIDE 2

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

slide-3
SLIDE 3

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!

slide-4
SLIDE 4

% 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

slide-5
SLIDE 5

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.

slide-6
SLIDE 6

... 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
  • ut the worker’s result.
slide-7
SLIDE 7

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(); } }

slide-8
SLIDE 8

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

slide-9
SLIDE 9

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

slide-10
SLIDE 10

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.

slide-11
SLIDE 11

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

slide-12
SLIDE 12

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!

slide-13
SLIDE 13

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

  • nly one thread is allowed to add to the

list at any point in time.

slide-14
SLIDE 14

Trouble in Concurrency City: Act 3

 Deadlock

 Program stops doing anything useful  All you need is 2 objects and 2 threads

slide-15
SLIDE 15

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

slide-16
SLIDE 16

Hands On Exercise

 Goal: Increment/decrement all ints in an array

Create class NumHolder, 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 11  Open the dropbox In-Class Exercise 8  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.