Transcript lec_5

Critical Reference
• An occurrence of a variable v is defined to be
critical reference:
a. if it is assigned to in one process and has an
occurrence in another process.
b. if it has an occurrence in an expression in one
process and is assigned to in another.
Limited Critical Reference
• A program satisfies the limited-criticalreference (LCR) restriction if each statement
contains at most one critical reference
• Consider the first occurrence of n in nn+1. It is
assigned to in process p and has (two) occurrences in
process q, so it is critical by (a).
• The second occurrence of n in nn+1 is critical by
(b) because it appears in the expression n n+1 in p
and is also assigned to in q.
• Consider now the version of the statements that uses
local variables. Again, the occurrences of n are
critical, but the occurrences of temp are not.
• Therefore, the program satisfies the LCR restriction.
LCR program
LCR
• Concurrent programs that satisfy the LCR
restriction yield the same set of behaviors
whether the statements are considered
atomic or are compiled to a machine
architecture with atomic load and store.
Volatile and Non-Atomic Variables
• Volatile variables
• The single statement in process q can be interleaved
at any place during the execution of the statements
of p.
• Because of optimization during compilation, the
computation in q may not use the most recent value
of n.
• The value of n may be maintained in a register from
the assignment in p1 through the computations in
p2, p3 and p4, and only actually stored back into n at
statement p5.
• Furthermore, the compiler may re-order p3 and 4 to
take advantage of the fact that the value of n+5
needed in p3 is computed in p4.
• These optimizations have no semantic effect
on sequential programs, but they do in
concurrent programs that use global variables,
so they can cause programs to be incorrect.
• Specifying a variable as volatile instructs the
compiler to load and store the value of the
variable at each use, rather than attempt to
optimize away these loads and stores.
• Concurrency may also affect computations
with multiword variables.
• A load or store of a full-word variable (32 bits
on most computers) is accomplished
atomically, but if you need to load or store
longer variables (like higher precision
numbers), the operation might be carried out
non-atomically.
• A load from another process might be
interleaved between storing the lower half and
the upper half of a 64-bit variable.
• If the processor is not able to ensure atomicity
for multiword variables, it can be
implemented using a synchronization
mechanism such as those to be discussed
throughout the book.
• However, these mechanisms can block
processes, which may not be acceptable in a
real-time system.
Concurrency Programs
• the normal execution of a program on a
computer is not the best way to study
concurrency.
• Later in this section, we discuss the
implementation of concurrency, because
eventually you will wish to write concurrent
programs using the constructs available in real
languages, but for studying concurrency there
is a better way.
Concurrent Counting Algorithm
The algorithm simply increments a global
variable twenty times, ten times in each of
two processes.
CS 556 – Distributed Systems
Tutorial on
Java Threads
Java Threads
Threads
• A thread is a lightweight process – a single sequential
flow of execution within a program
• Threads make possible the implementation of
programs that seem to perform multiple tasks at the
same time (e.g. multi-threaded Web servers)
• A new way to think about programming
Java Threads
Java Threads
We will cover:
• How to create threads in Java
Java Threads
How to create Java Threads
There are two ways to create a Java thread:
1.
Extend the java.lang.Thread class
2.
Implement the java.lang.Runnable interface
Java Threads
Extending the Thread class
• In order to create a new thread we may subclass
java.lang.Thread and customize what the thread
does by overriding its empty run method.
• The run method is where the action of the thread takes
place.
• The execution of a thread starts by calling the start
method.
Java Threads
Example I
class MyThread extends Thread {
private String name, msg;
}
public MyThread(String name, String msg) {
this.name = name;
this.msg = msg;
}
public void run() {
System.out.println(name + " starts its execution");
for (int i = 0; i < 5; i++) {
System.out.println(name + " says: " + msg);
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {}
}
System.out.println(name + " finished execution");
}
Java Threads
Example I
class MyThread extends Thread {
private String name, msg;
}
public MyThread(String name, String msg) {
this.name = name;
this.msg = msg;
}
public void run() {
System.out.println(name + " starts its execution");
for (int i = 0; i < 5; i++) {
System.out.println(name + " says: " + msg);
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {}
}
System.out.println(name + " finished execution");
}
Java Threads
Example I
class MyThread extends Thread {
private String name, msg;
}
public MyThread(String name, String msg) {
this.name = name;
this.msg = msg;
}
public void run() {
System.out.println(name + " starts its execution");
for (int i = 0; i < 5; i++) {
System.out.println(name + " says: " + msg);
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {}
}
System.out.println(name + " finished execution");
}
Java Threads
Example I (cont.)
public class test {
public static void main(String[] args) {
MyThread mt1 = new MyThread("thread1", "ping");
MyThread mt2 = new MyThread("thread2", "pong");
mt1.start();
the threads will run in parallel
mt2.start();
}
}
Java Threads
Example I (cont.)
• Typical output of the previous example:
thread1
thread1
thread2
thread2
thread1
thread2
thread1
thread2
thread1
thread2
thread1
thread2
thread1
thread2
starts its execution
says: ping
starts its execution
says: pong
says: ping
says: pong
says: ping
says: pong
says: ping
says: pong
says: ping
says: pong
finished execution
finished execution
Java Threads
Implementing the Runnable
interface
• In order to create a new thread we may also provide a class
that implements the java.lang.Runnable interface
• Preffered way in case our class has to subclass some other
class
• A Runnable object can be wrapped up into a Thread object
– Thread(Runnable target)
– Thread(Runnable target, String name)
• The thread’s logic is included inside the run method of the
runnable object
Java Threads
Example II
class MyClass implements Runnable {
private String name;
private A sharedObj;
public MyClass(String name, A sharedObj) {
this.name = name; this.sharedObj = sharedObj;
}
public void run() {
System.out.println(name + " starts execution");
for (int i = 0; i < 5; i++) {
System.out.println(name + " says: " + sharedObj.getValue());
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {}
}
System.out.println(name + " finished execution");
}
Java Threads
}
Example II (cont.)
class A {
private String value;
public A(String value) { this.value = value; }
public String getValue() {
return value;
}
}
shared variable
public class test2 {
public static void main(String[] args) {
A sharedObj = new A("some value");
Thread mt1 = new Thread(new MyClass("thread1", sharedObj));
Thread mt2 = new Thread(new MyClass("thread2", sharedObj));
mt1.start(); mt2.start();
}
}
Java Threads
Example II (cont.)
• Typical output of the previous example:
thread1
thread1
thread2
thread2
thread1
thread2
thread1
thread2
thread1
thread2
thread1
thread2
thread1
thread2
starts execution
says: some value
starts execution
says: some value
says: some value
says: some value
says: some value
says: some value
says: some value
says: some value
says: some value
says: some value
finished execution
finished execution
Java Threads
start() && join()
Java
• Concurrency is built in to the language.
– p.start() puts thread p in the ready (Enabled)
queue.
– p.join(), executed by main, suspends main until
thread p terminates.
throws
• If a method is capable of causing an exception
that it does not handle, it must specify this
behavior so that callers of the method can
guard themselves against that exception.
• You do this by including a throws clause in the
method’s declaration.
The throw statement
• throw expression ;
• The type of expression must be a subtype of
class Throwable.
• The enclosing block statement terminates
abruptly. The thrown exception may be caught
by a try-catch statement.
Class hierarchy (partial)
• Throwable
• Error
–
–
–
–
–
–
–
–
–
OutOfMemoryError
Exception
IOException
RuntimeException
ArithmeticException
IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
NegativeArraySizeException
The try-catch-finally statement
try
body
catch(E1 x1)
catchBody1
catch(E2 x2)
catchBody2
...
finally
finallyBody
try-catch with no finally
Concurrent Counting Algorithm
import java.lang.String;
import java.lang.Thread;
class Count extends Thread
{
//field
static volatile int n;
//constructor
void Count()
{
}
//method
public void run()
{
}
public static void main(String[] s0)
{
}
}
class Count extends Thread {
static volatile int n = 0;
public void run() {
int temp;
for (int i = 0; i < 10; i++) {
temp = n;
n = temp + 1;
}
}
public static void main(String[] args) {
Count p = new Count();
Count q = new Count();
p.start();
q.start();
try { p.join(); q.join(); }
catch (InterruptedException e) { }
System.out.println("The value of n is " + n);
}
}