This is an alternative way of creating threads in Java, and it is
often preferable to the one we have seen previous time (threads as extensions of Thread),
because:
Safety and liveness properties can be characterized precisely by using
Temporal Logic.
They corresponds to a special format of T.L. formulae.
However, for our purposes we will just use the above intuitive description
These general principles are relevant
also in sequential programming,
but in concurrent programming
there are far many more properties that need
to be satisfied in order for a program to be considered "correct"
More precisely, there are no infinite chains of "enabled" states for the same action
More precisely, there are no infinite chains in which the state "enabled"
for the same action
is present infinitely many times, and "executed" is present only finitely many times.
Note that the DF, LF solution to the dining philosophers seen before
is not strongly fair. Strong fairness is very difficult to achieve.
<APPLET CODE = "MyApplet.class">
<PARAM NAME = ... VALUE = ...>
</APPLET>
public class MyApplet extends Applet
implements Runnable {...}
Then we can create a thread with the statement
new Thread(this)
________ __________ __________ __________
| | target | | implmt | | extends | |
| Thread |------->| Runnable |<.......| MyRunbl |-------->| supercls |
|________| |__________| |__________| |__________|
| | | |
| run() | | run() |
|__________| |__________|
r
public class Semaphore {
private int value;
public Semaphore(int initial) {
value = initial;
}
synchronized public void up() {
++value;
notify();
}
synchronized public void down()
throws InterruptedException {
while (value == 0) wait;
--value;
}
}
package concurrency.semaphore;
import java.awt.*;
import java.applet.*;
import concurrency.display.*;
/********************************************************/
class MutexLoop implements Runnable {
Semaphore mutex;
MutexLoop (Semaphore sema) {mutex=sema;}
public void run() {
try {
while(true) {
while(!ThreadPanel.rotate());
// get mutual exclusion
mutex.down();
while(ThreadPanel.rotate()); //critical section
//release mutual exclusion
mutex.up();
}
} catch(InterruptedException e){}
}
}
/********************************************************/
public class SemaDemo extends Applet {
ThreadPanel thread1;
ThreadPanel thread2;
ThreadPanel thread3;
NumberCanvas semaDisplay;
public void init() {
setLayout(new BorderLayout());
semaDisplay = new NumberCanvas("Mutex");
add("Center",semaDisplay);
Panel p = new Panel();
p.add(thread1=new ThreadPanel("Thread 1",Color.blue,true));
p.add(thread2=new ThreadPanel("Thread 2",Color.blue,true));
p.add(thread3=new ThreadPanel("Thread 3",Color.blue,true));
add("South",p);
}
public void start() {
Semaphore mutex = new DisplaySemaphore(semaDisplay,1);
thread1.start(new MutexLoop(mutex));
thread2.start(new MutexLoop(mutex));
thread3.start(new MutexLoop(mutex));
}
public void stop() {
thread1.stop();
thread2.stop();
thread3.stop();
}
}
Usually termination is not an issue: interactive computations are "naturally" infinite
class Philosopher extends Thread {
private int identity;
private PhilCanvas view;
private Diners controller;
private Fork left;
private Fork right;
Philosopher(Diners ctr, int id, Fork l, Fork r) {
controller = ctr; view = ctr.display;
identity = id; left = l; right = r;
}
public void run() {
try {
while (true) {
//thinking
view.setPhil(identity,view.THINKING);
sleep(controller.sleepTime());
//hungry
view.setPhil(identity,view.HUNGRY);
right.get();
//gotright chopstick
view.setPhil(identity,view.GOTRIGHT);
sleep(500);
left.get();
//eating
view.setPhil(identity,view.EATING);
sleep(controller.eatTime());
right.put();
left.put();
}
} catch (java.lang.InterruptedException e) {}
}
}
Each philosopher flips a coin before choosing the fork. Once he has
acquired the first fork he looks for the other fork. If the latter is
not available, then
he releases the first fork
To be more precise, in this solution it is still possible that no philosopher ever gets to eat,
but this situation has probability 0.
class FixedPhilosopher extends Thread {
int identity;
boolean stopRequested = false;
PhilCanvas view;
Diners controller;
Fork left;
Fork right;
FixedPhilosopher(Diners controller, int identity, Fork left, Fork right) {
this.controller = controller;
this.view = controller.display;
this.identity = identity;
this.left = left;
this.right = right;
}
public void run() {
while (!stopRequested) {
try {
//thinking
view.setPhil(identity,view.THINKING);
sleep(controller.sleepTime());
//hungry
view.setPhil(identity,view.HUNGRY);
//get forks
if (identity%2 == 0) {
left.get();
view.setPhil(identity,view.GOTLEFT);
} else {
right.get();
view.setPhil(identity,view.GOTRIGHT);
}
sleep(500);
if (identity%2 == 0)
right.get();
else
left.get();
//eating
view.setPhil(identity,view.EATING);
sleep(controller.eatTime());
right.put();
left.put();
} catch (java.lang.InterruptedException e) {}
}
}
public void stopRequested() {
stopRequested = true;
}
}
blocked -> blocked ->
enabled -> enabled ->
enabled -> executed
blocked -> enabled -> blocked
-> enabled -> blocked ->
enabled -> executed
class RedCar implements Runnable {
...
public void run() {
try {
while(true) {
while (!display.moveRed(id)); // not on bridge
control.redEnter();
while (display.moveRed(id)); // move over bridge
control.redExit();
}
} catch (InterruptedException e){}
}
}
class BlueCar implements Runnable {
...
public void run() {
try {
while (true) {
while (!display.moveBlue(id)); // not on bridge
control.blueEnter();
while (display.moveBlue(id)); // move over bridge
control.blueExit();
}
} catch (InterruptedException e){}
}
}
class SafeBridge extends Bridge {
private int nred = 0;
private int nblue = 0;
synchronized void redEnter() throws InterruptedException {
while (nblue>0) wait();
++nred;
}
synchronized void redExit(){
--nred;
if (nred==0)
notifyAll();
}
synchronized void blueEnter() throws InterruptedException {
while (nred>0) wait();
++nblue;
}
synchronized void blueExit(){
--nblue;
if (nblue==0)
notifyAll();
}
}
class FairBridge extends Bridge {
private int nred = 0;
private int nblue = 0;
private int waitblue = 0;
private int waitred = 0;
private boolean blueturn = true;
synchronized void redEnter() throws InterruptedException {
++waitred;
while (nblue>0 || (waitblue>0 && blueturn)) wait();
--waitred;
++nred;
}
synchronized void redExit(){
--nred;
blueturn = true;
if (nred==0)
notifyAll();
}
synchronized void blueEnter() throws InterruptedException {
++waitblue;
while (nred>0 || (waitred>0 && !blueturn)) wait();
--waitblue;
++nblue;
}
synchronized void blueExit(){
--nblue;
blueturn = false;
if (nblue==0)
notifyAll();
}
}