Imprimer
Catégorie : Embedded Systems
Affichages : 412

1°/ Theory

 1.1°/ The problem 

1.2°/ principles

1.3°/ Implications

2°/ In Java

2.1°/ Creating threads

class MyThread extends Thread {
    int value;
    public MyThread(int value) { this.value = value; }
    public void run() {
       for(int i=0;i<1000000;i++) {
            System.out.println(value++);
        }
    }
}

2.2°/ Instanciation and execution.

class TestThread {
    public static void main(String[] args) {
        MyThread t1 = new MyThread(10);
        MyThread t2 = new MyThread(20);
        t1.start();
        t2.start();
    }
}

2.3°/ Sharing memory

class Box {
    int value;
    public Box() { value = 0; }
    public void inc(int v) { value += v; }
    public int get() { return value; }
}

class MyIncThread extends Thread {
    Box b;
    int incr;
    public MyIncThread(Box b, int incr) { this.b = b; this.incr = incr; }
    public void run() {
        for(int i=0;i<100;i++) {
            b.inc(incr);
            System.out.println(b.get());
        }
    }
}

class IncTest {
    public static void main(String[] args) {
        Box b = new Box();
        MyIncThread t1 = new MyIncThread(b,2);
        MyIncThread t2 = new MyIncThread(b,5);
        t1.start();
        t2.start();
    }
}

  

 

 

2.4°/ Fix the conflicts: mutex and event wait

 

 

2.4.1°/ Mutex.

 

 

 

 

principle 1 : current object locking with synchronized method.

class A {
    ...
    public void meth1() { ... }
    public synchronized void meth2() { ... }
    public synchronized void meth3() { ... }
}

 

principle 2 : locking the mutex of an auxiliary object, using  synchronized block.

class A {
    Object myMut;
    public A() { myMut = new Object(); ... }
    ...
    public void meth1() { ... }
    public synchronized void meth2() { ... }
    public void meth3() { 
        ...
        synchronized(myMut) {
            ....
        }
        ...
    }
}

 

2.4.2°/ Event wait

 

while ( ... ) {
    try {
        wait();
    }
    catch(InterruptedException e) {}
}
if ( ...) {
    notifyAll();
   ...
}

 

  

Example 1 : synchronization barrier for N threads

class Barrier {
    int nb; // nb to reach
    int in; // nb currently waiting
    public Barrier(int nb) { 
        this.nb = nb;
        in = 0;
    }
    public synchronized void enter() {
        in += 1;
        if (in == nb) {
            notifyAll();
        }
        else {
            while(in != nb) {
                try { wait(); }
                catch{InterruptedException e) {}
            }
        }
    }
}

Remarques :

 

Exemple 2 : the semaphore

class Semaphore {
    int nb; // nb tokens
    public Semaphore(int nb) { this.nb = nb; }
    public synchronized void put(int n) {
        nb += n; // put n tokens
    }
    public synchronized void get(int n) {
        while(n > nb) {
            try { wait(); }
            catch{InterruptedException e) {}
            nb -= n; // withdraw de n tokens
        }
    }
}

 

class Barrier {
    int nb; // nb to reach atteindre
    AtomicInteger in; // nb currently waiting
    Semaphore sem;
    public Barrier(int nb) { 
        this.nb = nb;
        in = new AtomicInteger();
        sem = new Semaphore(0); // 0 tokens
    }
    public void enter() {
        in.incrementAndGet(); // does in +=1 thread safely
        if (in.get() == nb) {
            in.set(0);
            sem.put(nb);
        }
        sem.get(1);
    }
}

Remarks :

 

Example 3 : producer/consummer

class Box {
    int value;
    boolean isEmpty;
    public Box() { value = 0; isEmpty = true; }
    public synchronized void put(int value) {
        while(!isEmpty) {
            try { wait(); } catch(InterruptedException e) {}
        }
        this.value = value;
        isEmpty = false;
        notifyAll()
    }
    public synchronized int get() {
        while(isEmpty) {
            try { wait(); } catch(InterruptedException e) {}
        }
        isEmpty = true;
        notifyAll();
        return value;
    }
class ThreadProd extends Thread {
    Box b;
    public ThreadProd(Box b) { this.b = b; }
    public void run() {
        while (true) {
            int val = ...; // tirage aléatoire
            b.put(val);
            sleep(val*10); // au dodo
        }
    }
}
class ThreadConso extends Thread {
    Box b;
    public ThreadConso(Box b) { this.b = b; }
    public void run() {
        while (true) {
            int val = ...; // tirage aléatoire
            sleep(val*10); // au dodo
            System.out.println(b.get());
        }
    }
}
class TestBox {
    public static void main(String[] args) {
        Box b = new Box();
        ThreadProd p = new ThreadProd(b);
        ThreadConso c = new ThreadConso(b);
        p.start(); c.start();
    }
}

Remarque : in this example, each thread calls a different method in the shared box, but the principles to wait/wake are unchanged.

 

2.5°/ Problems related to mutex/event wait

2.5.1°/ dead-lock

2.5.2°/ Starvation

2.5.3°/ Example : the 5 philosophers

class Fork {
    boolean isTaken;
    Thread owner;
    public Fork() { owner = null; isTaken = false; }
    public synchronized void take(Thread t) {
        if ((isTaken) && (t==owner)) return; // t has already the fork        while (isTaken) {
            try { wait(); } catch(InterruptedException e) {}
        }
        owner = t;
        isTaken = true;
    }
    public synchronized void put(Thread t) {
        if (!isTaken) return; // fork already put down
        if (t != owner) return; // bad thread
        isTaken = false;
        owner = null;
        notifyAll(); // wake up waiting threads
    }
}
class Philo extends Thread {
    Fork left; Fork right;
    public Philo(Fork f, Fork r) { left = l; right = r; }
    public void run() {
        while(true) {
            l.take(this);
            r.take(this);
            // manger
            l.put(this);
            r.put(this);
            //penser
        }
    }
}
class Philo extends Thread {
    int id; Fork left; Fork right;
    public Philo(int id, Fork f, Fork r) { 
        this.id = id; left = l; right = r; 
        if (id%2==0) {
            l.take(this);
            if (id != 4) r.take(this);
        }
    }
    public void run() {
        while(true) {
            l.take(this);
            r.take(this);
            // manger
            l.put(this);
            r.put(this);
            //penser
        }
    }
}
class Philo5 {
    public static void main(String[] args) {
        Fork[] forks= new Fork[5];
        Philo[] philos = new Philo[5];
        for(int i=0;i<5;i++) forks[i] = new Fork();
        for(int i=0;i<5;i++) philos[i] = new Philo(i,forks[i],forks[(i+1)%5]);
        for(int i=0;i<5;i++) philos[i].start();
    }
}