Download thread - UTEP Computer Science

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Concurrent
Programming
CS 3331
Chapter 11
1
Outline
What’re threads?
 How to create threads?
 How to controlling threads?
 Thread safety and synchronization
 BoundedQueue example

2
Background: Multitasking

Efficient use of expensive CPU time
 Fast
CPU and slow peripherals (I/O)
 Run another program while waiting for I/O
 Context switching among tasks or processes
 Shared memory vs. message-based (IPC)
 Built-in language features vs. library-based

Multithreading
 Shard
memory, lightweight multitasking
 No context switching of virtual memory space
3
Multithreaded Programming

Thread

A single sequential flow
of control within a
program, i.e., a
lightweight flow that
executes concurrently
with other threads within
a single process.
 Communicates with
other threads via shared
variables and objects.
 Java language feature
 Managed by JVM.
flow of control
sequential
concurrent
4
Why?
Can take advantages of multiple CPUs.
 Allows a server to handle multiple clients
simultaneously.
 Suitable for developing reactive system.
 Makes application more responsive to
user inputs (e.g., GUI programs such as
BouncingBall applet).
 Natural to model real worlds.

5
However,
More difficult to program and debug (e.g.,
shared access to objects)
 Nondeterministic order of thread execution
 Safety and liveness problems

6
Creating Threads in Java

Two approaches
 By
extending the java.lang.Thread class
 By implementing the java.lang.Runnable
interface
7
Creating Threads (Cont.)

Extending the Thread class
public class MyThread extends Thread {
public void run() {
// code to be run concurrently
}
}
// start a new thread by calling the start method
MyThread thread = new MyThread();
thread.start();
flow of control
start()
// …
run()
// Q: What happened if run is called directly?
thread.run()
// Q: Design pattern used?
The method run is the concurrent unit in Java.
8
Creating Threads (Cont.)

Implementing the Runnable interface
public interface Runnable {
void run();
}
public class MyRunnable implements Runnable {
public void run() {
// code to be concurrently
}
}
// create a new thread by passing a Runnable object and start it, e.g.,
new Thread(new MyRunnable()).start();
// or using anonymous inner class
new Thread(new Runnable() {
public void run() { /* concurrent code */ }
}).start();
// In Java 8 using lambda notation
new Thread(() -> { /* concurrent code */ }).start()
9
Example --- Simple Counter
public class Counter extends Thead {
private int count, inc, delay;
public Counter(int init, int inc, int delay) {
this.count = init; this.inc = inc; this.delay = delay;
}
public void run() {
try {
for (;;) {
System.out.print(count + “ “);
count += inc;
sleep(delay); // suspend delay miliseconds
}
} catch (InterruptedException e) {}
}
public static void main(String[] args) {
new Counter(0, 1, 33).start();
new Counter(0, -1, 100).start();
}
}
10
Example (Cont.)
Sample output:
0 0 1 2 -1 3 4 5 -2 6 7 8 -3 9 10 -4 11 12 13 -5 14 15 16 -6 17 18 -7 19
20 21 -8 22 23 24 -9 25 26 -10 27 28 -11 29 30 31 -12 32 33 34 -13 35
36 37 -14 38 39 -15 40 41 42 -16 43 44 45 …
Q: Run the program several times. Are the outputs the
same?
Q: What will happen if we change the statement “new
Counter().start()” to “new Counter().run()” in the main
method?
11
Exercise
Write a thread class named Talker that prints a hello message,
say “Hello, I am Tom!”, continuously and creates two instances of
Talker as separate threads.
public class Talker _______________________ {
private String name;
public Talker(String name) {
this.name = name;
}
}
12
Exercise
Work in a group of two or three to write a utility method named mul.
double[][] mul(double[][] a, double[][] b, int sizeOfSub)
 It computes the product of two matrices a and b concurrently, by
partitioning the result matrix into a number of submatrices of
size sizeOfSub * sizeOfSub and using a separate thread to
compute each submatrix. Assume that arguments are
rectangular or multiplication compatible; a and b are
multiplication compatible if a is of size l*n and b is of size n*m.
Use Thread.join() method to wait for the completion of another
thread.
 Write a sequential version of mul and compare the time
efficiency of the two; use System.currentTimeMillis().
13
Controlling Threads

Life cycle of threads

New


After creation but before start() call
Alive


After the start() call; run() is implicitly called.
Consists of two sub states



Runnable: Ready to run; maybe running or waiting for their turns
Non-runnable: Not ready to run; waiting for some events (e.g.,
sleeping, blocked, or waiting)
Dead

When run() method returns
New
Alive
start
yield
Runnable
sleep
join
Dead
end of
run
Non-runnable
14
Methods of Thread Class
Method
Description
start()
*sleep()
join()
Enter the Runnable state from the new state
Enter the Non-runnable (or blocked) state
Enter the Non-runnable state and wait for
another thread to terminate
Release CPU and remain in the Runnable
Cause InterruptedException
True if in the alive state
True if interrupted
*yield()
interrupt()
isAlive()
isInterrupted()
* static method
15
Example
Coordinating concurrent jobs
public class Job extends Thread {
public void run() {
// do some meaningful work, e.g., writing multithreaded applets.
}
public static void main(String[] args) {
Job[] jobs = new Job[10];
for (int i = 0; i < jobs.length; i++) {
jobs[i] = new Job();
jobs[i].start();
}
for (Job job: jobs) {
job.join();
}
}
main
jobs[0] … jobs[9]
}
16
Exercise
Explain the execution flow of the following program.
public class Job extends Thread {
public void run() {
// do some meaningful work, e.g., writing multithreaded applets.
}
public static void main(String[] args) {
Job[] jobs = new Job[10];
for (int i = 0; i < jobs.length; i++) {
jobs[i] = new Job();
jobs[i].start();
jobs[i].join();
}
}
}
17
Thread Safety

Example --- bank accounts
public class Account {
private long balance;
public boolean withdraw(long amount) {
if (amount <= balance) {
long newBalance = balance – amount;
balance = newBalance;
return true;
} else {
return false;
}
}
// other methods and fields
}

What might happen in the presence of multiple threads?
18
Example (Cont.)

One possible scenario
1 if (amount <= balance) {
2 long newBalance = balance – amount;
3 balance = newBalance;
4 return true;
}
Assume an account, say acc, with balance $1,000,000.
new Thread(() -> acc.withdraw(1000000)).start();
new Thread(() -> acc.withdraw(1000000)).start();
time balance
t1
t2
t3
t4
t5
t6
t7
t8
1,000,000
1,000,000
1,000,000
1,000,000
0
0
0
0
withdraw 1
withdraw 2
1: amount<=balance
1: amount<=balance
2: newBalance=...;
2: newBalance=...;
3: balance=...;
3: balance=...;
4: return true;
4: return true;
19
Atomicity of Operations

The problem
 Several
calls of the withdraw method may be
interleaved interfering with each others.

Atomic operation
 An
operation that can’t be interrupted, e.g.,
reading and assignment to (word-sized) variables.
 Non-atomic operations should be explicitly
synchronized to ensure atomicity.
20
Making methods atomic

Synchronized methods and statements

A lock is associated with each object.
// synchronized method
synchronized void aMethod() {
// do something
}
void aMethod() {
synchronized (this) {
// do something
}
}
// synchronized statement
synchronized (expr) { // expr should be of a reference type!
// do somthing
}
21
Example
public class Account {
private long balance;
public synchronized boolean withdraw(long amount) {
if (amount <= balance) {
long newBalance = balance – amount;
balance = newBalance;
return true;
} else {
return false;
}
}
// other methods and fields
}
22
Exercise
Make withdraw method synchronized by using the
synchronized statement.
public class Account {
private long balance;
public boolean withdraw(long amount) {
// WRITE YOUR CODE HERE…
if (amount <= balance) {
long newBalance = balance – amount;
balance = newBalance;
return true;
} else {
return false;
}
}
}
23
Synchronization

Synchronization
 Mechanism
to controls the order in which threads
execute
 Competition vs. cooperative synchronization

Competition---Mutual exclusion of threads
 Each
synchronized method or statement is
guarded by an object.
 When entering a synchronized method or
statement, the object will be locked until the
method is finished.
 When the object is locked by another thread, the
current thread must wait.
24
Example --- Bounded Queue
A first-in, first-out queue with a fixed capacity
public class BoundedQueue {
final protected int size; // capacity of the queue
protected Object rep[]; // circular array
protected int front = 0; // front of the queue
protected int back = -1; // back of the queue
protected int count = 0; // number of objects in the queue
public BoundedQueue(int size) {
this.size = size;
rep = new Object[size];
back = size – 1;
}
public boolean isEmpty() {
return count == 0;
}
*Refer to java.util.concurrent for thread-safe collections.
*Refactor the code to a generic class.
25
Bounded Queue (Cont.)
public boolean isFull() { return count == size; }
public int count() { return count; }
public void put(Object e) {
if (!isFull()) {
back = (back + 1) % size;
rep[back] = e;
count++;
}
}
public Object get() {
Object result = null;
if (!isEmpty()) {
result = rep[front];
front = (front + 1) % size;
count--;
}
return result;
}
}
26
Making Queue Thread-Safe
public class SyncBoundedQueue extends BoundedQueue {
public SyncBoundedQueue(int size) { super(size); }
public synchronized boolean isEmpty() { return super.isEmpty(); }
public synchronized boolean isFull() { return super.isFull(); }
public synchronized int count() { return super.count(); }
public synchronized void put(Object e) { super.put(e); }
public synchronized Object get() { return super.get(); }
}
Thread-safe but maybe less efficient!
27
Use of Bounded Queue
Typical use in producers and consumers
Thread
Producer
Consumer
SyncBoundedQueue
28
Producer
public class Producer extends Thread {
private BoundedQueue queue;
private int n; // number of items to produce
public Producer(BoundedQueue queue, int n) {
this.queue = queue;
this.n = n;
}
public void run() {
for (int i = 0; i < n; i++) {
queue.put(i);
System.out.println(“produced: “ + i);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {}
}
}
}
29
Consumer
public class Consumer Thread {
private BoundedQueue queue;
private int n; // number of stolen items to sell
public Consumer(BoundedQueue queue, int n) {
this.queue = queue;
this.n = n;
}
public void run() {
for (int i = 0; i < n; i++) {
Object obj = queue.get();
System.out.println(“\tconsumed: “ + obj);
try {
sleep((int) (Math.random() * 400));
} catch (InterruptedException e) {}
}
}
}
30
Sample Main Program
The main method of class SyncBoundedQueue
public static void main(String[] args) {
SyncBoundedQueue queue = new SyncBoundedQueue(5);
new Producer(queue, 15).start(); // produce 15 items
new Consumer(queue, 10).start(); // consume 10 items
}
Output
Some of the items might be lost, as the producer produces items
faster than the consumer consumes them.
31
Why Items Get Lost?
public void put(Object e) {
if (!isFull()) {
back = (back + 1) % size;
rep[back] = e;
count++;
}
}
public Object get() {
Object result = null;
if (!isEmpty()) {
result = rep[front];
front = (front + 1) % size;
count--;
}
return result;
}
}
32
Cooperation among Threads

Guarded suspension




Before a method is executed, the guard is tested. A guard is
the precondition for an action to complete successfully.
Execution continues only when the guard is true, ensuring
the successful completion of the method invocation.
Execution is temporarily suspended until the guard becomes
true, at which time execution may continue.
Thread controlling methods


wait(), notify(), and notifyAll() defined in the class Object
Can be used to implement guarded suspension
33
Thread Methods of Class Object
Method
Description
wait()
Temporarily blocked and placed in the wait queue
of the receiving object.
notify() Awaken one of the threads in the wait queue
associated with the receiving object and remove it
from the queue.
notifyAll() Same as notify() except that all threads in the wait
queue are awakened.
waiting
Object
Queue<Thread>
obj.wait(): add current thread to obj’s wait queue
obj.notify(): awake a thread from obj’s wait queue
34
Bounded Queue with Guarded
Suspension
public class BoundedQueueWithGuard extends BoundedQueue {
public Producer(int size) {
super(size);
}
public synchronized boolean isEmpty() {
return super.isEmpty();
}
public synchronized boolean isFull() {
return super.isFull();
}
public synchronized int getCount() {
return super.getCount();
}
<<put, get, and main method>>
}
35
Put/Get Methods
public synchronized void put(Object obj) {
try {
while (isFull()) { // suspend till queue becomes not full
wait(); // wait for notification
}
} catch (InterruptedException e) {}
super.put(e);
notify();
}
public synchronized void get(Object obj) {
try {
while (isEmpty()) { // suspend till queue becomes not full
wait(); // wait for notification
}
} catch (InterruptedException e) {}
super.get(e);
notify();
}
36
Smart Producer and Consumer
public static void main(String args[]) {
BoundedQueueWithGuard queue = new BoundedQueueWithGuard(5);
new Producer(queue, 15).start(); // produce 15 items.
new Consumer(queue, 15).start(); // consume 15 times
}
Output:
No lost items!
37
Exercise
 Implement a thread-safe, bounded Stack class with
guarded suspension. Define operations such as pop,
push, isFull, and isEmpty. Test your code by using
classes similar to Producer/Consumer classes.
 Extend your JavaChat application so that when a
user sends an RSVP message the user is prohibited
from sending a further message until at least one
response is received.
 RSVP message: a message starting with “rsvp:”
 Response: a message starting with “ack:”
 Improve to use a separate thread to send messages;
use BoundedQueueWithGuard.
38