concurrency - purdue university · concurrency • side note: code that uses concurrency tends to...

55
Concurrency John Ross Wallrabenstein

Upload: others

Post on 29-May-2020

26 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

ConcurrencyJohn Ross Wallrabenstein

Page 2: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Updates• Project 3

• Have you started?

• Updates: a few errors have been fixed

• Download updated code

• Add your solution so far

• Minimal Coding Involved

• Requires solid understanding of Concurrency

Page 3: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Reference Type Review

• Primitives - the actual value is held at the memory address of the variable

• Class Types - a reference to the class location in the heap is held at the memory address

• A reference is another name for a pointer

See http://cslibrary.stanford.edu/104/ for more!

Page 4: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Project 3 Hint

• TicketServer should have exactly one TicketDatabase object

• Why shouldn’t we ever clone TicketDatabase?

Page 5: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Project 3 Hint

• TicketServer should have exactly one TicketDatabase object

• Why shouldn’t we ever clone TicketDatabase?

• Answer: We need each client to operate on the same object so that updates to the database are universal

Page 6: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Example

Source: Absolute Java, by Walter Savitch p. 278

MyClass x = new MyClass("John Doe", 50);MyClass y = x;y.setName("Jane Doe");y.setAge(45);System.out.println("Name is: " + x.getName());System.out.println("Age is: " + x.getAge());

Name is: Jane DoeAge is: 45

Class X

name = John Doe

age = 50

X

Class X

name = John Doe

age = 50

X

YClass X

name = Jane Doe

age = 45

X

Y

Here, Y updates the same object pointed to by X

Page 7: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency

What examples of concurrency are we familiar with?

http://www.youtube.com/v/ErZi9GwjHBI&hl=en&fs=1&autoplay=1

Page 8: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency

• Motivation: Modern computer CPU design facilitates concurrency through multiple processors

• Rather than increase the clock speed or operations per second of an individual processor, we simply add more processors

Page 9: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency

• When tasks execute in sequence, they are executed one after the other

• When tasks execute in parallel, they are executed simultaneously

Page 10: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency

• By writing code that can execute multiple tasks in parallel, we gain a significant advantage by having multiple processors

• Sequential tasks are unable to use the processing power available

Page 11: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency

• Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor

• This is due to the overhead involved in creating each concurrent task

Today we learn what this “overhead” is

Page 12: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

• Definitions of concurrency vary depending on your operating system

Concurrency Definitions

Page 13: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

• Definitions of concurrency vary depending on your operating system

• {MacOS,Linux,UNIX} - Executing multiple processes simultaneously*

Concurrency Definitions

* so you can open your bottle of scotch sooner

Page 14: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

• Definitions of concurrency vary depending on your operating system

• {MacOS,Linux,UNIX} - Executing multiple processes simultaneously*

• Windows - Multiple processes failing simultaneously

Concurrency Definitions

* so you can open your bottle of scotch sooner

Page 15: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency Definitions

• A thread is a separate computation process

• Each parallel task should be given its own thread

Page 16: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Threads• In Java, a thread is an object of the class

Thread

• Building a thread class is easy!

• We examine two methods for creating a thread

1. Extend Thread

2. Implement Runnable

2. Both are acceptable

Page 17: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Extending Thread

public class MyThreadedClass extends Thread{ //Optional Instance Variables //Optional Methods public void run(){ //Begin Task Work Here } }

Page 18: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Using a Threaded Class

• Instantiate a new instance of your class

• Call the start() method

• This calls the run() method in your class

• Why does start() call run()?

• Why not call run() directly()?

MyThreadedClass c = new MyThreadedClass();c.start();

More about this shortly

Page 19: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Implementing Runnable

• An alternate method is to implement the runnable interface

• Changes to the class are trivial

• Significant changes to the way we start the thread

Page 20: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Implementing Runnable

public class MyRunnable implements Runnable{ //Optional Instance Variables //Optional Methods public void run(){ //Begin Task Work Here } }

Page 21: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Using the Thread

• Create a new Thread object

• Pass a new MyRunnable object as a parameter

• Call start() on the Thread object

Thread t = new Thread(new MyRunnable());t.start();

Page 22: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Using the Thread

• Create a new Thread object

• Pass a new MyRunnable object as a parameter

• Call start() on the Thread object

Thread t = new Thread(new MyRunnable());t.start();

Wait, this isn’t stored in a variable??

Page 23: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Confusing Issues

• The class Thread has its own run() method, however we do not want to use that method as it is not specific to our class

• Instead, we will define our own run() method within our threaded class

• Since both Thread and our class have a method named run(), how does Java choose the correct one?

Page 24: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

start() vs run()

• Previously, I gave a hand-waving explanation as to why start() must be used over run()

• Goal: We want our new thread to execute its run() method, rather than the class containing the statement myThread.run()

Page 25: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

start() vs run()

• What actually happens in the following code?

public class MyThreadedClass extends Thread{ public void run(){...} }

public class ClassA{ public void myMethod(){ myThreadedClass t = new MyThreadedClass(); t.run(); } }

Page 26: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

start() vs run()

• A better question: Does ClassA wait for t.run() to finish?

Page 27: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

start() vs run()

• A better question: Does ClassA wait for t.run() to finish?

• Answer: YES

• But how is this multithreaded??

Page 28: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

start() vs run()

• A better question: Does ClassA wait for t.run() to finish?

• Answer: YES

• But how is this multithreaded?

• IT ISN’T

Page 29: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Why• Last time, I mentioned that start()

performed some additional overhead work to set up the thread’s execution

• This “overhead” creates the thread as a process independent of the calling process

• This is how we achieve multi-threading

• If we don’t call start(), we don’t get a separate process!

Page 30: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Using Threaded Classes

• Threaded classes do not need instance variables

• If a threaded class happens to have none, why not make the run() method static?

Page 31: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Useful Thread Methods

• join() - This forces the execution of the calling method to stop until the thread has finished executing

• sleep(long milliseconds) - This forces the thread to pause execution for the specified amount of time

• wait() and notify() - More on this in a moment

Think about how this is different from just

calling run()

Page 32: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

join() vs. run()

• I just explained that run() does not create a thread, forcing the calling process to wait for it to complete

• However, if we have a thread pool, we can have a calling process wait until all threads die

• But the threads still execute in parallel

Page 33: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Example

• This executes the entire run() method for thread 1, then the entire run() method for thread 2, etc.

• This is sequential execution!

public class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public void threadPool(){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i) threads.get(i).run(); } }

Page 34: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

public class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public void threadPool(){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i) threads.get(i).start(); for(int i = 0; i < threads.size(); ++i) threads.get(i).join(); System.out.println(“Done”); } }

• This starts all threads concurrently

• Then, we join() ClassA’s execution with all threads

• ClassA waits until all threads have finished, but the threads run concurrently

Executes only after all threads

have finished

Page 35: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Pitfall

• Why can’t we just do this?public class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public void threadPool(){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i){ threads.get(i).start(); threads.get(i).join(); } System.out.println(“Done”); } }

Page 36: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Pitfall

• We lose concurrencypublic class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public void threadPool(){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i){ threads.get(i).start(); threads.get(i).join(); } System.out.println(“Done”); } }

This waits until thread i has finished!

Page 37: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Why we need join()

• Consider the following code:

public class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public static void main(String args[]){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i) threads.get(i).start();

System.out.println(“Done”); } }

Page 38: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Why we need join()

• What happens after “Done” is printed?

public class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public static void main(String args[]){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i) threads.get(i).start();

System.out.println(“Done”); } }

What happens

after this?

Page 39: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Why we need join()• main() exits and the program terminates

• Even if the threads are not done!public class ClassA{ private ArrayList<Thread> threads = new ArrayList<Thread>(5);

public static void main(String args[]){ for(int i = 0; i < threads.size(); ++i) threads.add(new MyThreadedClass()); for(int i = 0; i < threads.size(); ++i) threads.get(i).start();

System.out.println(“Done”); } }

Page 40: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Concurrency Issues

Page 41: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Race Conditions

• Race Condition - two threads attempt to access a shared resource simultaneously

• Project 3 - The TicketDatabase!

• Not terribly important to worry about

• I mean, they are only responsible for...

Page 42: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •
Page 43: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Therac-25

• Therac-25: A radiation therapy machine produced by AECL

• Contained a race condition

• Responsible for the deaths of two patients

• Administered 100x Recommended Radiation Dose

Page 44: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Of course, this never happens anymore...

Page 45: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Current Events• Buying a Toyota

• Pro: You won’t get a ticket for driving fast

• Con: You can’t stop (and might die)

You don’t want to make the CEO of your company this mad

You also probably don’t want to write code that can kill people

(society frowns on this)

Page 46: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Blaming the Floor Mats

• Does everyone see why Toyota so desperately tried to blame:

1. Floor Mats

2. Sticky Accelerator

• ... rather than the computer?

• No one wants to be the next Therac-25

Page 47: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

wait() and notify()

• In lecture, you discussed wait() and notify()

• Why are these methods useful?

Page 48: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Shared Resources

• When resources are shared amongst multiple threads, we introduce the possibility of deadlock

• Deadlock - a circular waiting for resources, where threads are unable to make progress

Page 49: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Dining Philosophers

• Philosopher: A being who has exactly two states: Eating and Thinking

• Aside: Change Major forms in HOVD 45

• Consider the scenario where five philosophers go to a Chinese restaurant...

Page 50: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Pretend this is a chopstick

And this is a Chinese Meal

Page 51: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Problem Setup• Each Philosopher models a Thread

• To move to the Eat state, the philosopher obtains the following resources:

• Chopstick on Left

• Chopstick on Right

• Philosophers are not sanitary creatures

• (and thus share eating utensils)

Page 52: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Deadlock

• What happens when each philosopher picks up the chopstick to their left?

Page 53: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Deadlock Solution• Each philosopher attempts to obtain a

resource (left or right chopstick)

• If the left chopstick is obtained, but the right is in use, release the lock on the left chopstick using wait().

• If both resources are obtained, complete the task (eating) and then notify() the philosophers that you are done so that they can obtain the resources

Page 54: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Questions

Page 55: Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to execute more slowly than sequential code on machines with a single processor •

Quiz