cs884 (prasad)java8threads1 concurrent programming multithreading

48
CS884 (Prasad) java8Threads 1 Concurrent Programming Multithreading

Upload: godwin-warner

Post on 02-Jan-2016

230 views

Category:

Documents


0 download

TRANSCRIPT

CS884 (Prasad) java8Threads 1

Concurrent Programming

Multithreading

CS884 (Prasad) java8Threads 2

• Multiprocessing– Using Multiple Processors.

• Multiprogramming (Batch)– Switch and execute different jobs simultaneously,

to improve CPU utilization.• Multitasking (Interactive)

– Perform more than one task at a time for each user, to improve response time.

• Multithreading– Threads in a user task (process) can share code, data,

and system resources, and access them concurrently. Each thread has a separate program counter, registers,

and a run-time stack.

CS884 (Prasad) java8Threads 3

Threads• A single sequential flow of control (of

execution of expressions and statements) is called a thread.

• A thread independently executes Java code, but may share address space with others. (cf. Process)– In Java, class/instance variables, and array

components are shareable among threads; local variables and formal parameters are not.

CS884 (Prasad) java8Threads 4

Multithreading is general, convenient, & efficient

paradigm for implementing interactive systems.

• Independent/cooperating input/processing/display

activities.

• In single-threaded systems, each application is

responsible for interleaving these activities through

polling or interrupts.

• In multi-threaded systems, these activities are

interleaved using a general time-slicing external to

the application.

CS884 (Prasad) java8Threads 5

Multithreading on uni-processor • ConsCons: Thread scheduling overheads.

• ProsPros:

� Concurrency necessary for natural description and fair execution of applications involving shared resources. Multithreaded systems reduce programmer burden by factoring out scheduling.

� Improves resource utilization as it incorporates demand-based scheduling and prevents starvation.

� Improves responsiveness in interactive systems by assigning priorities to threads and using preemption.

� Enables flexible control of one thread from another thread. (E.g., stop, suspend, resume etc.)

CS884 (Prasad) java8Threads 6

Further Multi-threading Examples

• In multimedia applications (e.g., playing audio and/or video concurrently).

• Performing I/O concurrently with scrolling a document (e.g., downloading image with a separate “controller” thread).

• Periodic updating of the screen with data acquired in real-time (e.g., Sports Ticker, Stock Quotes, Advertisements, etc.).

CS884 (Prasad) java8Threads 7

Java Primitives and Examples

CS884 (Prasad) java8Threads 8

• Mutual exclusion construct is based on Hoare’s monitor.

• synchronized methods in a class cannot be run concurrently on behalf of different threads.

• Recursive call or Calls to synchronized methods permitted in the same thread.

• synchronized statement locks an object.• “Object” is an instance of a class (incl. class Class).

• To synchronize “producers” and “consumers” Hoare uses wait/signal on condition variables.

• wait() / notify() / notifyAll() etc. enable threads to communicate/regulate each other’s progress.

CS884 (Prasad) java8Threads 9

Creating and Running Threads• Define subclass of class Thread.

Override run() method.• public void run() { }

• Create an instance of the subclass, and invoke start() on it. Now run() method executes in an independent thread.

• Threads can also be created from an instance of a class implementing the interface Runnable.

• Required when the class is defined by extension.

CS884 (Prasad) java8Threads 10

Example using class Threadclass Echo extends Thread { public void run() { while (true) System.out.println(“ABC”); } public static void main (String[] args) { new Echo() . start(); new Echo() . start(); }}

CS884 (Prasad) java8Threads 11

1 ABC1 ABC1 ABC1 ABC2 ABC2 ABC2 ABC2 ABC2 ABC1 ABC1 ABC2 ABC2 ABC2 ABC1 ABC . . .

> javac Echo.java > java Echo

1 ABC2 ABC2 ABC2 ABC1 ABC1 ABC2 ABC2 ABC2 ABC2 ABC2 ABC1 ABC1 ABC1 ABC

...

1 ABC1 ABC1 ABC1 ABC1 ABC1 ABC1 ABC1 ABC1 ABC

...

Solaris

Windows

with yield() in both OS

1 ABC2 ABC1 ABC2ABC1 ABC2 ABC1ABC2 ABC1 ABC2 ABC

...

CS884 (Prasad) java8Threads 12

Example using interface Runnableclass Echo implements Runnable { public void run() { try { while (true) { Thread.sleep(10); System.out.println(“ABC”); } } catch (InterruptedException e) { return; } } public static void main (String[] args) { Runnable r = new Echo(); new Thread(r) . start(); }}

CS884 (Prasad) java8Threads 13

Example of Sharingclass Shared { private int cnt = 0; void print(String Id) { synchronized (this) { System.out.print(Id + “:” + cnt ); System.out.println( “-” + ++cnt); } }}

class Shared { private int cnt = 0; synchronized void print(String Id) { System.out.print(Id + “:” + cnt ); System.out.println( “-” + ++cnt); }}

CS884 (Prasad) java8Threads 14

Threads sharing an object

class SharingThread extends Thread {

private static Shared s = new Shared();

String Id;

SharingThread (String Name) { Id = Name;

start();}

public void run () { while (true) { s.print(Id); } }

public static void main (String [] args) {

new SharingThread(“A”) ;

new SharingThread(“B”) ; }

}

CS884 (Prasad) java8Threads 15

Motivation for Mutual ExclusionConcurrent AccessConcurrent Access Mutual Exclusion with yield()

A:368-369A:369-370B:370-371A:370-372A:372-373A:373-374A:374-375B:371-376B:376-377B:377-378B:378-379B:379A:375-381A:381-382A:382-383A:383-384-380

A:828-829B:829-830B:830-831A:831-832B:832-833A:833-834B:834-835A:835-836B:836-837B:837-838A:838-839B:839-840

A:693-694A:694-695A:695-696B:696-697B:697-698B:698-699B:699-700B:700-701B:701-702A:702-703A:703-704A:704-705A:705-706

...

CS884 (Prasad) java8Threads 16

Interaction of Language Features

run() method case study

cs480 (Prasad) L11Threads 17

Subclassing : Access Control class Thread { ... public void run() { }}class SubThread extends Thread { public void run() { ... }

// ILLEGAL // void run() { ... }

}

• Otherwise, run() can be invoked on a SubThread instance via (its reference in) a Thread variable (due to dynamic binding) in another package.

cs480 (Prasad) L11Threads 18

Subclassing : Exception class Thread { ... public void run() { }}class SubThread extends Thread { public void run() { ... }

// ILLEGAL // public void run() throws InterruptedException { // sleep(1000); }

}

• Otherwise,run() invoked on a SubThread instance via a Thread variable (by dynamic binding) can violate the contract that run() of class Thread does not throw any exception.

CS884 (Prasad) java8Threads 19

Synchronized• It is illegal to use synchronized for constructors and for

method declarations in interfaces. • Can abstract methods be synchronized?

• A synchronized method can override or be overridden by a non-synchronized method. However, this does not alter “synchronized”-status of the overridden method accessible using super.

• The locks are released when synchronized statements and synchronized method invocations complete abruptly by throwing an exception.

CS884 (Prasad) java8Threads 20

Synchronized Methods• When two threads invoke synchronized instance

(static) methods simultaneously on the same object, only one thread is permitted exclusive access to the instance (static) fields of the object (class).

• When two threads invoke synchronized instance methods simultaneously on the same object, the static fields of the class are not locked.

• A thread can access fields of an object using a non-synchronized method even when the object is locked by another thread executing a synchronized method.

CS884 (Prasad) java8Threads 21

Methods in class Object• public final void wait() throws InterruptedException {...}

• Current thread is suspended (after atomically releasing the lock on this) until some other thread invokes notify() or notifyAll() or interrupts.

• public final void notify() {...}• Notifies exactly one thread waiting on this object for

a condition to change. The awakened thread cannot proceed until this thread relinquishes the lock.

• public final void notifyAll() {...}• Notifies all the threads waiting on this object.

These methods must be invoked inside synchronized code or else IllegalMonitorStateException will be thrown.

CS884 (Prasad) java8Threads 22

Simplified Bounded-Buffer Problem

CS884 (Prasad) java8Threads 23

Simplistic 1-Cell Bufferclass Buffer { Object x; // synchronized public void put (Object _x, String id) { System.out.println( "Done << " + id + " puts " + _x); x = _x; } // synchronized public Object get (String id) { System.out.println( "Done >> " + id + " gets " + x); return x; }}

CS884 (Prasad) java8Threads 24

class Producer extends Thread { private Random r = new Random(); Buffer b; String id; public Producer(Buffer _b, String _id) { b = _b; id = _id; } public void run () { int delay; Integer ir;

try { while (true) {

delay = Math.abs(r.nextInt() % 1999) + 50; sleep(delay); ir = new Integer(delay); System.out.println("Ready << "+id+" puts "+ ir);

b.put(ir, id); }

}catch (Exception e){System.out.println("Exception$ " + e);};

}}

CS884 (Prasad) java8Threads 25

class Consumer extends Thread { private Random r = new Random(); Buffer b; String id; public Consumer(Buffer _b, String _id) { b = _b; id = _id; } public void run () { int delay; Integer ir = null; try { while (true) { delay = Math.abs(r.nextInt() % 1999) + 50; sleep(delay); System.out.println("Ready >> " + id + " gets ");

ir = (Integer) b.get(id); } } catch (Exception e) {System.out.println("Exception$ " + e);};

}}

CS884 (Prasad) java8Threads 26

Producer-Consumer : Bounded Buffer

public class PCB { public static void main(String[] args) { Buffer b = new Buffer(); new Consumer(b,"C1") . start(); new Producer(b,"P1") . start(); try {Thread.sleep(1000); } catch (Exception e){}; new Consumer(b,"C2") . start(); new Producer(b,"P2") . start();

}}

CS884 (Prasad) java8Threads 27

Unfettered Run

Ready >> C1 getsReady << P2 puts 493Done >> C1 gets nullDone << P2 puts 493Ready << P1 puts 1591Done << P1 puts 1591Ready << P1 puts 488Done << P1 puts 488Ready >> C2 getsDone >> C2 gets 488Ready >> C1 getsDone >> C1 gets 488Ready >> C2 getsDone >> C2 gets 488Ready << P1 puts 745Done << P1 puts 745 ...

...Ready << P2 puts 815Done << P2 puts 815Ready >> C2 getsDone >> C2 gets 815Ready << P1 puts 1223Done << P1 puts 1223Ready >> C1 getsDone >> C1 gets 1223Ready << P2 puts 403Done << P2 puts 403Ready >> C2 getsDone >> C2 gets 403 ...

(transient stability?!)

CS884 (Prasad) java8Threads 28

Concurrency controlConcurrency control : class Buffer class Buffer { Object x; boolean empty = true; public synchronized void put

(Object _x, String id) throws Exception { ...} public synchronized Object get (String id) throws Exception { ... }}

• Two producers (consumers) cannot put(get) two items in (from) the same buffer slot simultaneously.

• A consumer (producer) is not permitted to get (put) an item from (into) buffer if empty (full).

CS884 (Prasad) java8Threads 29

public synchronized void

put (Object _x, String id) throws Exception {

while (!empty) wait();

empty = ! empty;

System.out.println("Done << "+id+" puts "+ _x);

x = _x;

notifyAll();

}

• Note that if-then cannot replace while because

notifyAll, due to a consumer, can wake up two

waiting producers, and only one producer will find the

buffer empty. (“race condition”)

CS884 (Prasad) java8Threads 30

public synchronized Object

get (String id) throws Exception { while (empty) wait(); empty = ! empty; System.out.println("Done >> "+id+" gets "+x); notifyAll(); return x;}• Note that notify cannot always be used in place of notifyAll because a consumer may be woken up.

• while required because notifyAll due to a producer does not guarantee that wait ing consumers will find a buffer element to read.

CS884 (Prasad) java8Threads 31

Synchonization and Mutual Exclusion

Ready >> C2 getsReady >> C1 getsReady << P1 puts 1672Done << P1 puts 1672Done >> C2 gets 1672Ready << P2 puts 774Done << P2 puts 774Done >> C1 gets 774Ready << P1 puts 168Done << P1 puts 168Ready >> C1 getsDone >> C1 gets 168Ready << P2 puts 1263Done << P2 puts 1263Ready >> C1 getsDone >> C1 gets 1263 …

...Ready << P1 puts 622Done << P1 puts 622Ready >> C1 getsDone >> C1 gets 622Ready >> C2 getsReady << P2 puts 1447Done << P2 puts 1447Done >> C2 gets 1447Ready << P2 puts 96Done << P2 puts 96Ready << P2 puts 95Ready >> C1 getsDone >> C1 gets 96Done << P2 puts 95 ...

CS884 (Prasad) java8Threads 32

Bounded-Buffer Problem

CS884 (Prasad) java8Threads 33

Bounded Buffer class Queue { private int c, front = 0, rear = 0, count = 0; private int [] q; Queue(int capacity) { c = capacity; q = new int [c]; } public synchronized void insert (int i) throws InterruptedException { … } public synchronized int delete () throws InterruptedException { … }

}

CS884 (Prasad) java8Threads 34

public synchronized void insert (int i) throws InterruptedException {

while (count == c) wait(); q[rear] = i; rear = (++rear) % c; count++; notifyAll(); } public synchronized int delete () throws InterruptedException { while (count == 0) wait(); --count; notifyAll(); int t = front; front = (++front) % c; return q[t]; }

CS884 (Prasad) java8Threads 35

Producerclass ProducerThread extends Thread {

private String Id;

private Queue buf;

private int init;

ProducerThread(String Name,Queue q,int i) {

Id = Name;

buf = q;

init = i;

}

public void run() { … }

}

CS884 (Prasad) java8Threads 36

public void run() {

try {

while (true) {

sleep(10); System.out.println("Produced by " +

Id + " " + init);

buf.insert(init++);

}

} catch (InterruptedException e) { System.exit(0);

}

}

CS884 (Prasad) java8Threads 37

Consumerclass ConsumerThread extends Thread {

private String Id;

private Queue buf;

ConsumerThread (String Name, Queue q ) {

Id = Name;

buf = q;

}

public void run() { … }

}

CS884 (Prasad) java8Threads 38

public void run() {

try {

while (true) {

sleep( (new java.util.Random()).nextInt() % 19 ); System.out.println("Consumed by " + Id

+ buf.delete());

}

} catch (InterruptedException e) { System.exit(0);

}

}

CS884 (Prasad) java8Threads 39

Driver Programpublic class TestBuffer { static Queue buffer = new Queue(11);

public static void main (String [] args) { ProducerThread p1 =

new ProducerThread("P1:", buffer, 0); ProducerThread p2 =

new ProducerThread("P2:", buffer, 10000); ConsumerThread c1 =

new ConsumerThread("C1:", buffer); ConsumerThread c2 =

new ConsumerThread("C2:", buffer); p1.start();

p2.start(); c1.start();

c2.start(); }}

CS884 (Prasad) java8Threads 40

Priority, Blocking, Scheduling

+

Semantic subtleties

CS884 (Prasad) java8Threads 41

Thread Priority • Range : MIN_PRIORITY ... NORM_PRIORITY ... MAX_PRIORITY

• A thread inherits its creator’s priority. It can be inspected (changed) at any time using getPriority (setPriority).

• Generally, the continuously running part of an application should run in a lower-priority thread, while the thread dealing with rarer events such as user input should have higher-priority.

• When a thread dies, its object does not go away, so its state can still be accessed.

CS884 (Prasad) java8Threads 42

Thread States

CS884 (Prasad) java8Threads 43

Blocked Thread

• A thread is blocked (that is, it is not runnable) if it is: – sleeping.– suspended.– waiting.– executing a “blocked” method. – “blocked” for I/O.

• Java neither detects nor prevents deadlocks. • Other Methods:

– yield(), join(), etc.

CS884 (Prasad) java8Threads 44

Thread Scheduling

• Java runs a non-blocked (runnable) highest-priority thread.

• A thread can be preempted by a higher priority thread that becomes runnable.

• The scheduler may however choose to run lower priority thread, to avoid starvation.

• The same (highest) priority threads are run in round-robin fashion.

CS884 (Prasad) java8Threads 45

• JVM on Windows uses time-slicing to schedule same priority threads. (“Fair policy”)

• JVM on Solaris chooses one of the same priority threads to run until the thread voluntarily relinquishes the CPU (by sleeping, yielding, or exiting), or until a higher priority thread preempts it.

CS884 (Prasad) java8Threads 46

Kinds of Thread • User and Daemon.

• Each application starts off as a user thread (main()).

• A thread’s status can be inspected (changed to daemon

before starting it ) using getDaemon() (setDaemon(true)).

• Threads inherit user/daemon status from their creator.

• An application runs until all user threads have completed.

When the last user thread completes, any remaining

daemon threads are stopped.

– To make the application exit when the original thread

dies, mark all the created threads daemon.

CS884 (Prasad) java8Threads 47

Example: Non-determinism class Sample { int a = 1, b = 2; void h() { a = b + 10; } void t() { b = a + 100;} }If two different threads concurrently execute h() and t(), then• If h() and t() are synchronized, then the post condition is:

– ( a = 12 b = 11( b = 101 a = 111• If h() and t() are not synchronized, then: (“non-exhaustive”)

– If all vars written back: ...( a = 12 b = 101– If all vars not written back: ( a = 1 b =

( a = 12 b = 2 ( a = 1 b = 101

CS884 (Prasad) java8Threads 48

Example: Out-of-order writes class Simple { int a = 1, b = 2; void synchronized t() { a = 3; b = 4; } void f() { System.out.println(a + “ ” + b); } }• assign a (use a) precedes assign b (use b) in t() (f()).• t() synchronized, so both a and b written back finally.• f() not synchronized, so its actions interleaved with t()’s.• No restrictions on the order of reads / writes of different

variables from memory.

– f(): read(a), t(): write(a), t(): write(b), f(): read(b);

– Finally: a = 3 and b = 4.

– Printed: 1 4