Concurrency - Purdue University · Concurrency • Side Note: Code that uses concurrency tends to...

Preview:

Citation preview

ConcurrencyJohn Ross Wallrabenstein

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

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!

Project 3 Hint

• TicketServer should have exactly one TicketDatabase object

• Why shouldn’t we ever clone TicketDatabase?

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

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

Concurrency

What examples of concurrency are we familiar with?

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

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

Concurrency

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

• When tasks execute in parallel, they are executed simultaneously

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

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

• Definitions of concurrency vary depending on your operating system

Concurrency Definitions

• 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

• 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

Concurrency Definitions

• A thread is a separate computation process

• Each parallel task should be given its own thread

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

Extending Thread

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

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

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

Implementing Runnable

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

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

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??

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?

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

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

start() vs run()

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

start() vs run()

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

• Answer: YES

• But how is this multithreaded??

start() vs run()

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

• Answer: YES

• But how is this multithreaded?

• IT ISN’T

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!

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?

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

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

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

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

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

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!

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

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?

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

Concurrency Issues

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...

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

Of course, this never happens anymore...

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)

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

wait() and notify()

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

• Why are these methods useful?

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

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...

Pretend this is a chopstick

And this is a Chinese Meal

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)

Deadlock

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

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

Questions

Quiz

Recommended