13: concurrency

32
13: Concurrency Definition: A thread is a single sequential flow of control within a program. Some texts use the name lightweight process instead of thread. A thread is similar to a real process in that a thread and a running program are both a single sequential flow of control. However, a thread runs within the context of a full-blown program and takes advantage of the resources allocated for that program and the program's environment. As a sequential flow of control, a thread must carve out some of its own resources within a running program. (It must have its own execution stack and program counter for example.)

Upload: virote

Post on 05-Jan-2016

29 views

Category:

Documents


1 download

DESCRIPTION

13: Concurrency. Definition:   A thread is a single sequential flow of control within a program. Some texts use the name lightweight process instead of thread. A thread is similar to a real process in that a thread and a running program are both a single sequential flow of control. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 13: Concurrency

13: Concurrency

• Definition:  A thread is a single sequential flow of control within a program. • Some texts use the name lightweight process instead of thread. • A thread is similar to a real process in that a thread and a running program

are both a single sequential flow of control. • However, a thread runs within the context of a full-blown program and takes

advantage of the resources allocated for that program and the program's environment.

• As a sequential flow of control, a thread must carve out some of its own resources within a running program. (It must have its own execution stack and program counter for example.)

Page 2: 13: Concurrency

import java.util.Timer;import java.util.TimerTask;public class Reminder { Timer timer; public Reminder(int seconds) { timer = new Timer(); timer.schedule(new RemindTask(), seconds*1000); } class RemindTask extends TimerTask { public void run() { System.out.println("Time's up!"); timer.cancel(); //Terminate the timer thread } } public static void main(String args[]) { System.out.println("About to schedule task."); new Reminder(5); System.out.println("Task scheduled."); }}

Using the Timer and TimerTask Classes

Page 3: 13: Concurrency

import java.util.Timer;import java.util.TimerTask;public class Reminder2 { Timer timer; public Reminder2(int seconds) { timer = new Timer(); timer.schedule(new RemindTask(), 0, seconds*1000); } class RemindTask extends TimerTask { public void run() { System.out.println("Time's up!"); } } public static void main(String args[]) { System.out.println("About to schedule task."); Reminder2 p=new Reminder2(3); System.out.println("Task scheduled."); try{ Thread.sleep(10*1000); }catch(Exception e){} p.timer.cancel(); //Terminate the timer thread }}

Performing a Task Repeatedly

Main Thread

Timer Thread

Page 4: 13: Concurrency

Customizing a Thread's run Method • There are two ways for creating a new

thread: – Subclassing Thread and Overriding method

run()– Implementing the Runnable Interface

• To trigger the execution of new threads, call the start() method in the Thread class.

Page 5: 13: Concurrency

The Life Cycle of a Thread

Page 6: 13: Concurrency

class SimpleThread extends Thread { public SimpleThread(String str) { super(str); } public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getName()); try { sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println("DONE! " + getName());}}public class TwoThreadsDemo { public static void main (String[] args) { new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start();

}}

Subclassing Thread and Overriding run 0 Jamaica0 Fiji1 Fiji1 Jamaica2 Jamaica2 Fiji3 Fiji3 Jamaica4 Jamaica4 Fiji5 Jamaica5 Fiji6 Fiji6 Jamaica7 Jamaica7 Fiji8 Fiji9 Fiji8 JamaicaDONE! Fiji9 JamaicaDONE! Jamaica

Page 7: 13: Concurrency

public class RunnableThread implements Runnable { private int countDown = 5; public String toString() { return "#" + Thread.currentThread().getName() + ": " + countDown; } public void run() {

while(true) { System.out.println(this); if(--countDown == 0) return;

} } public static void main(String[] args) {

for(int i = 1; i <= 5; i++) new Thread(new RunnableThread(), "" + i).start(); // Output is like SimpleThread.java

} } ///:~

Implementing the Runnable Interface

Page 8: 13: Concurrency

A Runnable interface simply has a run( ) method,—it doesn’t produce any innate threading abilities, like those of a class inherited from Thread.

So to produce a thread from a Runnable object, you must create a separate Thread object, handing the Runnable object to the special Thread constructor.

Rule of Thumb:  If your class must subclass some other class (the most common example being Applet), you should use Runnable.

Implementing the Runnable Interface

Page 9: 13: Concurrency

The Life Cycle of a Thread• Creating a Thread

– clockThread = new Thread(this, "Clock");

• Starting a Thread – clockThread.start();

• Making a Thread Not Runnable .A thread becomes Not Runnable when one of these events occurs: – Its sleep method is invoked. – The thread calls the wait method to wait for a specific condition to be

satisifed. – The thread is blocking on I/O.

Page 10: 13: Concurrency

The Life Cycle of a Thread• Stopping a Thread

– A thread arranges for its own death by having a run method that terminates naturally.

public void run() { Thread myThread = Thread.currentThread(); while (clockThread == myThread) {

…….}}public void stop() {clockThread = null; }

• The isAlive() Method– The isAlive() method returns true if the thread has been started and

not stopped. – If the isAlive() method returns false, you know that the thread either

is a New Thread or is Dead. – If the isAlive() method returns true, you know that the thread is

either Runnable or Not Runnable.

Page 11: 13: Concurrency

Yielding you can use yield method to tell the thread scheduling mechanism that you’ve done

enough and that some other thread might get the CPU.

public class YieldingThread extends Thread { private int countDown = 5; private static int threadCount = 0; public YieldingThread() {

super("" + ++threadCount); start();

} public String toString() {

return "#" + getName() + ": " + countDown; } public void run() {

while(true) { System.out.println(this); if(--countDown == 0) return; yield();

} }

Page 12: 13: Concurrency

Daemon threads A “daemon” thread is one that is supposed to provide a general service in the

background as long as the program is running, but is not part of the essence of the program. Thus, when all of the non-daemon threads complete, the program is terminated.

public class SimpleDaemons extends Thread { public SimpleDaemons() {

setDaemon(true); // Must be called before start() start();

} public void run() {

while(true) { try { sleep(100); } catch (InterruptedException e) {

throw new RuntimeException(e); } System.out.println(this); }

} public static void main(String[] args) {

for(int i = 0; i < 10; i++) new SimpleDaemons(); } } ///:~

Page 13: 13: Concurrency

Sharing limited resourcespublic class AlwaysEven implements Runnable{ private int i; public void next() {

i++; i++; //do sth else } public int getValue() { return i; } public void run() { while(true) { int val = getValue(); if(val % 2 != 0) { System.out.println(val); System.exit(0); } } } public static void main(String[] args) { final AlwaysEven ae = new AlwaysEven(); (new Thread(ae) ).start(); while(true) ae.next(); }} ///:~

Page 14: 13: Concurrency

Sharing limited resources• This example shows a fundamental problem with using

threads. You never know when a thread might be run.

– Imagine sitting at a table with a fork, about to spear the last piece of food on your plate, and as your fork reaches for it, the food suddenly vanishes (because your thread was suspended and another thread came in and stole the food).

• Preventing this kind of collision is simply a matter of putting a lock on a resource when one thread is using it.

– The first thread that accesses a resource locks it, and then the other threads cannot access that resource until it is unlocked,.

Page 15: 13: Concurrency

Resolving shared resource contention• Java has built-in support to prevent

collisions over resources in the form of the

synchronized keyword. synchronized void f() { /* ... */ } synchronized void g(){ /* ... */ }

• Each object contains a single lock. – When you call any synchronized method, that ob

ject is locked and no other synchronized method of that object can be called by other thread until the first one finishes and releases the lock.

Page 16: 13: Concurrency

Resolving shared resource contention

synchronized

synchronized

Thread-1 Thread-2

Page 17: 13: Concurrency

Resolving shared resource contentionpublic class AlwaysEven2 implements Runnable{

private int i;

public synchronized void next() { i++; i++; }

public synchronized int getValue() { return i; }

public void run() {

while(true) {

int val = getValue();

if(val % 2 != 0) {

System.out.println(val);

System.exit(0);

}

}

}

public static void main(String[] args) {

final AlwaysEven2 ae = new AlwaysEven2();

(new Thread(ae) ).start();

while(true)

ae.next();

}

} ///:~

Page 18: 13: Concurrency

Critical sections• Sometimes, you only want to prevent multiple

thread access to part of the code inside a method instead of the entire method.

synchronized(syncObject) { // This code can be accessed // by only one thread at a time

} • This is also called a synchronized block; before it c

an be entered, the lock must be acquired on syncObject. – If some other thread already has this lock, then the critic

al section cannot be entered until the lock is given up.

Page 19: 13: Concurrency

Resolving shared resource contentionpublic class AlwaysEven2 implements Runnable{ private int i; public void next() { synchronized(this) { i++; i++; } } public int getValue() { synchronized(this){ return i; } } public void run() { while(true) { int val = getValue(); if(val % 2 != 0) { System.out.println(val);

System.exit(0); } } } public static void main(String[] args) { final AlwaysEven2 ae = new AlwaysEven2(); (new Thread(ae) ).start(); while(true) ae.next(); }} ///:~

Page 20: 13: Concurrency

Cooperation between threads• In order to make threads cooperate with each other, Java

provides mechanism of handshaking between threads:– Implemented using the Object methods wait( ) and notify( ) /

notifyAll( ).

• Typically, wait( ) is used when you’re waiting for some condition to change (typically, this condition will be changed by another thread).

• You may just idly wait while testing the condition inside your thread; ( called a “busy wait” and it’s a very bad use of CPU cycles. )

• wait( ) allows you to put the thread to sleep while waiting for the condition to change, and only when a notify( ) or notifyAll( ) occurs does the thread wake up and check for changes. Thus, wait( ) provides a way to synchronize activities between threads.

Page 21: 13: Concurrency

Producer-consumer Model

ProducerConsumer

Storehouse

Product

Thread A Thread B

Page 22: 13: Concurrency

Cooperation between threads ( 1)public class ProducerConsumer extends Object {

  private Object slot;

  public ProducerConsumer() {    slot = null; // null indicates empty  }

  public synchronized void putIn(Object obj)             throws InterruptedException {

    while ( slot != null ) {      wait();     }

    slot = obj;  // put object into slot    notifyAll(); // signal that slot has been filled  }

  public synchronized Object takeOut()             throws InterruptedException {

    while ( slot == null ) {      wait(); // wait while slot is empty    }

    Object obj = slot;    slot = null; // mark slot as empty    notifyAll(); // signal that slot is empty    return obj;  }

Page 23: 13: Concurrency

Cooperation between threadsWait and notify / notifyAll• wait( ) allows you to put the thread to sleep while

waiting for some condition .• only when a notify( ) or notifyAll( ) occurs does the

thread wake up and check for changes.• the only place you can call wait( ), notify( ), or

notifyAll( ) is within a synchronized method • It’s important to understand that sleep( ) does not

release the lock when it is called. On the other hand, the method wait( ) does release the lock

• When a thread enters a call to wait( ) inside a method, that thread’s execution is suspended, and the lock on that object is released.

Page 24: 13: Concurrency

Cooperation between threads• There are two forms of wait( ). The first takes an argument in

milliseconds that has the same meaning as in sleep( ): – The object lock is released during the wait( ). – You can come out of the wait( ) due to a notify( ) or notifyAll( ), or

by letting the clock run out.

• The second form of wait( ) takes no arguments; this version is more commonly used. – This wait( ) continues indefinitely until the thread receives a

notify( ) or notifyAll( ).

• One fairly unique aspect of wait( ), notify( ), and notifyAll( ) is that these methods are part of the base class Object and not part of Thread, as is sleep( ).

• Although this seems a bit strange at first, it’s essential because they manipulate the lock that’s also part of every object.

• As a result, you can put a wait( ) inside any synchronized method, regardless of whether that class extends Thread or implements Runnable.

Page 25: 13: Concurrency

Cooperation between threads

You can ask another object to perform an operation that manipulates its own lock. – For example, if you want to notify( ) an object

x, you must do so inside a synchronized block that acquires the lock for x:

synchronized(x) {

……x.notify();

}

Page 26: 13: Concurrency

Cooperation between threadsclass CubbyHole {

    private int contents;    private boolean available = false;    public synchronized int get() {        while (available == false) {            try {                wait();            } catch (InterruptedException e) { }        } //available now, available=true

//we get the content

//and reset the flag

        available = false;        notifyAll();        return contents;    }

public synchronized void put(int value) {       while (available == true) {            try {                wait();            } catch (InterruptedException e) { }        }       //empty now, available=false

//we set the content

//and set the flag

  contents = value;        available = true;        notifyAll();    }}

Page 27: 13: Concurrency

Cooperation between threads ( 2)class Consumer extends Thread {

    private CubbyHole cubbyhole;

    public Consumer(CubbyHole c) {        cubbyhole = c;    }

    public void run() {        int value = 0;        for (int i = 0; i < 10; i++) {            value = cubbyhole.get();            System.out.println("Consumer #"   + " got: " + value);        }    }}

Page 28: 13: Concurrency

Cooperation between threads ( 2)class Producer extends Thread {

    private CubbyHole cubbyhole;   

     public Producer(CubbyHole c) {        cubbyhole = c;     }

    public void run() {        for (int i = 0; i < 10; i++) {            cubbyhole.put(i);            System.out.println("Producer #" + " put: " + i);            try {                sleep((int)(Math.random() * 100));            } catch (InterruptedException e) { }        }    }}

Page 29: 13: Concurrency

Cooperation between threadspublic class ProducerConsumerTest {

    public static void main(String[] args) {        CubbyHole c = new CubbyHole();        Producer p1 = new Producer(c);        Consumer c1 = new Consumer(c);

        p1.start();        c1.start();    }}

Page 30: 13: Concurrency

Exercises1. Create an example of a “busy wait.” One thread sleeps f

or awhile and then sets a flag to true. The second thread watches that flag inside a while loop (this is the “busy wait”) and when the flag becomes true, sets it back to false and reports the change to the console.

2. Create a second version of the above exercise program that uses wait( ) instead of the “busy wait” flag .

Page 31: 13: Concurrency

Cooperation between threads ( 1)public class ProducerConsumer extends Object {

  private Object slot;

  public ProducerConsumer() {    slot = null; // null indicates empty  }

  public synchronized void putIn(Object obj)             throws InterruptedException {

    while ( slot != null ) {      wait();     }

    slot = obj;  // put object into slot    notifyAll(); // signal that slot has been filled  }

  public synchronized Object takeOut()             throws InterruptedException {

    while ( slot == null ) {      wait(); // wait while slot is empty    }

    Object obj = slot;    slot = null; // mark slot as empty    notifyAll(); // signal that slot is empty    return obj;  }

public static void main(String[] args) {    final ProducerConsumer ch = new ProducerConsumer();

    Runnable runA = new Runnable() {        public void run() {          try {            String str;            Thread.sleep(500);

            str = "multithreaded";            ch.putIn(str);            str = "programming";            ch.putIn(str);

            str = "with Java";            ch.putIn(str);          } catch ( InterruptedException x ) {            x.printStackTrace();          }        }      };

Page 32: 13: Concurrency

Cooperation between threads ( 1)Runnable runB = new Runnable() {

        public void run() {          try {            Object obj;

            obj = ch.takeOut();            System.out.println("in run() - just took out: '" +                 obj + "'");

            Thread.sleep(500);

            obj = ch.takeOut();            System.out.println("in run() - just took out: '" +                 obj + "'");

            obj = ch.takeOut();            System.out.println("in run() - just took out: '" +                 obj + "'");          } catch ( InterruptedException x ) {            x.printStackTrace();          }        }      };

    Thread threadA = new Thread(runA, "threadA");    threadA.start();

    Thread threadB = new Thread(runB, "threadB");    threadB.start();  }  }