Download Thread

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

Object-oriented programming wikipedia , lookup

Class (computer programming) wikipedia , lookup

Name mangling wikipedia , lookup

C Sharp syntax wikipedia , lookup

Java (programming language) wikipedia , lookup

Java performance wikipedia , lookup

C++ wikipedia , lookup

Scheduling (computing) wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

Join-pattern wikipedia , lookup

Thread (computing) wikipedia , lookup

Monitor (synchronization) wikipedia , lookup

Transcript
Concurrent Programming
in Java
Dr. Zoltan Papp
Motivation: event driven, responsive
systems
Sequential approach:
while ( true ) {
do event = getEventId()
while ( event == null );
switch ( event ) {
case E1: action1(); break;
case E2: action2(); break;
.
.
}
}
Properties:
- not a “nice” structure (e.g. extendibility)
- not always responsive
Parallel approach:
E2
E1
action1
E3
Properties:
action2
action3
- direct event – action association
- independent, parallel execution
New concepts
Process/thread/task
single chain of instruction execution
Interprocess communication
share common resources
synchronization
Concurrent programming:
introduces these concepts in programming languages
(i.e. new programming primitives)
investigates how to build compound systems safely
Processes/threads/tasks
Main conflict:
numberOf(threads) >> numberOf(processors)
 processor sharing  scheduling
Process/thread states:
running
scheduler
decision
“wait for event”
“yield”
runnable
“event”
blocked
#(running) = 0 .. number of processors
#(runnable) = 0 .. arbitrary
Scheduler’s main operations:
save thread context
restore thread context
pass control to thread
select thread to run: policy!
Scheduling schemes
Aspect 1: thread selection
priority based
round-robin
FIFO
or any combination of these...
Aspect 2: moments of event evaluation
non-preemptive (“cooperative scheduling”)
preemptive
Java threads
java.jang package:
public class Thread
extends Object implements Runnable
public abstract interface Runnable
For details check the class documentation!
Java thread scheduling:
priority based
inside priority groups: round-robin
preemptive
time slicing: platform dependent – not guaranteed!
Java thread definition 1: implementing the Runnable interface
class NewThread implements Runnable {
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
thread 1
public class TD1 {
public static void main(String args[]) {
Thread t = new Thread(new NewThread(), "Child Thread");
thread 2
t.start();
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
start new
thread
just wait for
a while
Java thread definition 2: extending the Thread class
class NewThread extends Thread {
NewThread(String name) { super(name); }
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
constructor
for the new
thread class
thread 1
}
public class TD2 {
public static void main(String args[]) {
Thread t = new NewThread("Child Thread"); // create a new thread
t.start();
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
thread 2
start new
thread
just wait for
a while
Interprocess communication
Common resources: the problem
thread 1:
.
.
i11;
i12;
i13;
i14;
.
.
R
critical
region
thread 2:
.
.
i21;
i22;
i23;
i24;
.
.
For certain resources: access must be mutually exclusive
Mutual exclusion rule for protected resources:
Let C denote the union of critical regions ci for resource R. T is
the set of threads tj having access to R. The mutual exclusive
access to R is satisfied if at any time instance only at most one
tj  T executes ck  C.
On programming language level: explicit notation for critical regions.
On runtime system level: implementing the rule
Example 1: Not synchronized resource access
// This program is not synchronized.
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run() {
target.call(msg);
}
}
Example 1: Not synchronized resource access (cont’d)
class Synch1 {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
Mutual exclusion in Java
Synchronized methods:
class Whatever {
.
.
synchronized ReturnType method(...) {
.
}
}
Operation: synchronized method executions are serialized
Example 2: Synchronized resource access
// This program is not synchronized.
class Callme {
synchronized void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run() {
target.call(msg);
}
}
Synchronized statements:
.
.
synchronized ( object ) {
<statements to be synchronized>
}
Operation: “lock” is associated with object
Example 3: Resource access via synchronized statements
// The code is the same as that of Example 1 - except the
// ‘run’ method body
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
Important: NO MAGIC!
class Whatever {
.
synchronized ReturnType method(...) {
<BODY>
}
}
class Whatever {
.
ReturnType method(...) {
synchronized (this) { <BODY> }
}
}
THE TWO SOLUTIONS ARE EQUIVALENT!
Thread synchronization in Java
Implementation: via special operations (invoked by threads)
java.lang.Object:
public final native void wait(long timeout)
throws InterruptedException;
public final void wait()
throws InterruptedException;
public final native void notify();
public final native void notifyAll();
The “fine details”: direct control of thread state transitions
java.lang.Thread:
public static final int MAX_PRIORITY;
public static final int MIN_PRIORITY;
public static final int NORMAL_PRIORITY;
public static native void sleep(long millis)
throws InterruptedException;
public static boolean interrupted();
public static native void yield();
The “fine details” (cont’d)
java.lang.Thread:
public final int getPriority();
public final void setPriority();
public void interrupt();
public boolean isInterrupted();
public final synchronized void join(long millis)
throws InterruptedException;
public void join()
throws InterruptedException;
The “fine details” (cont’d)
java.lang.Thread:
public final void suspend();
public final void resume();
public final synchronized void stop(Throwable o);
public final void stop();
Thread state transitions in Java 1.1 and earlier
new
new
start
runnable
stop
dead
resume
yield,
scheduler time slice
stop
suspend
suspended
suspend
notify, notifyAll,
IO compl, sleep exp,
join compl.
stop, term
running
stop
IO, sleep,
wait, join
blocked
resume
IO compl.
blockedsusp.
suspend
Thread state transitions in Java 1.2
new
new
start
runnable
yield,
scheduler time slice
running
term
dead
IO, sleep,
wait, join
notify, notifyAll,
IO compl, sleep exp,
join compl.
blocked
Reasons for the “clean-up”: stop() and suspend() are inherently
unsafe!
- they encourage “messy” program structures
- coherent “lock” states are difficult (or impossible)
to maintain
- they can result in corrupted data
Example 1: suspend/resume in Java 1
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
}
Example 1: suspend/resume in Java 1 (cont’d)
class SusRes1 {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.suspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.resume();
System.out.println("Resuming thread One");
ob2.suspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.resume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Example 2:
suspend/resume
in Java 2
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) { while(suspendFlag) wait();}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
Example 2:
suspend/resume
in Java 2
(cont’d)
class SusRes2 {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming thread One");
ob2.mysuspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Semaphores (locks):
resource  lock
Implementation: primitive data type + operations (atomic)
E.g. semaphore + P, V operations
V(s): s := s + 1;
P(s): if s == 0 then wait_until( s  0 ); s := s - 1;
Usage:
Thread 1:
semaphore s1 = 1; /* to protect R1 resource
initial value: free */
.
.
P(s1);
/* lock R1 if available */
<operations on R1>
V(s1);
/* free R1 */
.
.
Example: Semaphores in Java
public class Semaphore {
long sem;
public Semaphore(long init) {
sem = init;
}
public synchronized void P() throws InterruptedException {
while ( sem == 0 ) wait();
sem -= 1;
}
public synchronized void V() {
sem += 1;
notifyAll();
}
public boolean isDown() {
return sem == 0;
}
}