threads cs 3250 some of these slides contain material by professor chuck allison

30
Threads CS 3250 me of these slides contain material by Professor Chuck Alli

Upload: david-lambert

Post on 02-Jan-2016

213 views

Category:

Documents


0 download

TRANSCRIPT

Threads

CS 3250

Some of these slides contain material by Professor Chuck Allison

What is a thread?

an independent unit of execution within a process

a path of execution through a program

a "lightweight process"

Sharing (or not)

Threads share the same address space and share the heap

+ Easy to communicate with other threads

- Possibility of inconsistent states

Each thread has its own execution stack

Multi-threaded vs. Single-threaded

Advantages of using more than one thread:

Single-threaded processes can't easily handle concurrent activities e.g., waiting for user I/O, network I/O, and

doing calculations at the same time Better performance if more than one

processor No guarantees Can sometimes get better performance

even if there's only one CPU. How?

Multi-threaded vs. Single-threaded

Disadvantages of using more than one thread: Race conditions and deadlock One thread can accidentally modify

another's resources. Have to deal with synchronization. Concurrency can lead to worse performance

rather than better.

Pitfalls Watch out for libraries that aren’t

thread-safe Don’t make any assumptions about

when threads will execute. Don’t use reasoning like “that will

hardly ever happen”. Testing is necessary but not

sufficient. Test on a variety of systems.

Pitfalls

Only use threads when appropriate.

“Fortunately, correct programs are frequently the simplest and have the most elegant design. Complexity should be avoided wherever possible.”

Windows System Programming, p. 223

// Illustrates Independent Threadsclass MyThread extends Thread{ private int count; public MyThread(String name, int count) { super(name); // Optional thread name this.count = count; } public void run() { for (int i = 0; i < count; ++i) System.out.println(getName()); }}

A First Example

Example by Professor Chuck Allison

public class Independent{ public static void main(String[] args) { Thread t1 = new MyThread("DessertTopping", 8); Thread t2 = new MyThread("FloorWax", 4); t1.start(); t2.start(); }}

Main program launches 2 threads

Define run(), call start()

DessertToppingDessertToppingDessertToppingFloorWaxDessertToppingFloorWaxDessertToppingFloorWaxDessertToppingFloorWaxDessertToppingDessertTopping

Output(Dependent on platform and environment -

YMMV)

The Runnable Interface

Alternative to extending java.lang.Thread

Declares a run( ) method 2 virtues:

Separates task from thread objects Leaves you free to extend another

class Java only supports single inheritance

Thread has a constructor that takes a Runnable object

class MyTask implements Runnable { private int count; private String name;

public MyThread(String name, int count){this.count = count;this.name = name;

}

public void run(){ for (int i = 0; i < count; ++i) System.out.println(name); }}

The Runnable interface

public class IndependentR { public static void main(String[] args) { Thread t1 = new Thread(

new MyTask("DessertTopping", 8)); Thread t2 = new Thread(

new MyTask("FloorWax", 4)); t1.start(); t2.start(); }}

Create threads fromRunnable objects

Blocking I/O Note that the calls to println( ) run

uninterrupted I/O is a blocking operation

The thread waits until it completes Other threads may run, but the I/O will be

undisturbed Reason: I/O is coarse-grained native code

JDK 1.4 java.nio provides non-blocking I/O Buffers, channels, selectors, for more fine-

grained control One thread can manage multiple

connections

Interleaved I/Oclass MyThread extends Thread{ // <snip> public void run() { for (int i = 0; i < count; ++i) { display(); // Replaces println() } } void display() { String s = getName(); for (int i = 0; i < s.length(); ++i) System.out.print(s.charAt(i)); System.out.println(); }} Example by Professor Chuck Allison

Output (interleaved – oops!)

DessertToppingDFloorWaxFloorWaxFloorWaxFloorWessertToppingDesaxsertToppingDessertToppingDessertToppingDessertToppingDessertToppingDessertTopping

Race Conditionresult of executing program(s) depends on who runs precisely when

b = getBalance(“1234”);b += 500;setBalance(“1234”, b);

b = getBalance(“1234”);

b -= 100;setBalance(“1234”, b);

Thread 1 Thread 2

balance starts at 1000

What should the ending balance be? What will it be?Will getting rid of the local variable b solve the problem?How can we solve this problem?

Synchronization

Need to prevent race conditions Critical region

Part of a program that accesses shared memory (or another shared resource)

To prevent race conditions, only allow one thread at a time to enter critical region

Locks and Monitors Every object has a hidden lock object

Used to protect code blocks Monitor concept

Only allows one thread in at a time Thread acquires a lock via some object Other related threads wait until lock is

released Applies to all guarded methods for that

object only Achieved with the synchronized

keyword Protects code (not data directly) Make data private!

synchronized void f(){ <protected code>}

How synchronized works(conceptually)

Very important. Why?

void f() {this.lock.acquire();try{ <protected code>}finally{ this.lock.release();}}

is the same as the following pseudocode…

Library Example

Check-out system Usually solved by database locks, but

humor me Book class Must only allow one thread access

to check-out check-in code Synchronized methods

// Illustrates synchronized methods

class Book{ private final String title; private final String author; private String borrower;

public Book(String title, String author) { this.title = title; this.author = author; borrower = null; }

public synchronized boolean checkOut(String borrower) { if (isAvailable()) { this.borrower = borrower; return true; } else return false; }

public synchronized boolean checkIn() { if (!isAvailable()) { borrower = null; return true; } else return false; }

public String getTitle() { return title; }

public String getAuthor() { return author; }

public synchronized boolean isAvailable() { return borrower == null; }

public synchronized String getBorrower() { return borrower; }}

Principles Always make data private Always protect access to shared

data with a monitor (i.e., using synchronized)

Synchronize as little code as possible Blocks instead of entire methods:

{… synchronized (obj) {…} … }

Synchronizing displayclass MyThread extends Thread{ private static Object lock = new Object(); // <snip>

void display() {

synchronized(lock) { String s = getName(); for (int i = 0; i < s.length(); ++i) System.out.print(s.charAt(i)); System.out.println();

} }}

DessertToppingFloorWaxDessertToppingDessertToppingFloorWaxDessertToppingDessertToppingFloorWaxDessertToppingDessertToppingFloorWaxDessertTopping

Output (not interleaved)

A simpler way of synchronizing display

synchronized static void display(String s){

for (int i = 0; i < s.length(); ++i)System.out.print(s.charAt(i));

System.out.println();}

Will use lock on class object

Threads and Exceptions

Exceptions belong to a thread Both are stack-based

When an exception occurs in a monitor, the lock is released

For uncaught exceptions, the current thread dies ThreadGroup.uncaughtException() is

called, which prints the stack trace as its default behavior

Deadlock

Circular wait e.g., Breakfasting Kindergarteners,

pirate map

Order access to resources All or nothing requests for

resources Must get everything requested or

nothing