多线程并发示例

多线程并发

模拟避免死锁的哲学家进餐问题

来自 《Cracking Coding Interview 6th Programming》

筷子:

class Chopstick {

    private Lock lock;

    public Chopstick() {
        lock = new ReentrantLock();
    }

    public void pickUp() {
        lock.lock();
    }

    public void putDown() {
        lock.unlock();
    }

}

哲学家:

class Philosopher extends Thread {

    private int bites = 10;
    private Chopstick left, right;

    public Philosopher(Chopstick left, Chopstick right) {
        this.left = left;
        this.right = right;
    }

    public void eat() {
        pickUp();
        chew();
        putDown();
    }

    public void pickUp() {
        left.pickUp();
        right.pickUp();
    }

    public void chew() {}

    public void putDown() {
        right.putDown();
        left.putDown();
    }

    public void run() {
        for (int i = 0; i < bites; i++) {
            eat();
        }
    }

}

上述代码,当所有哲学家都同时拿起左边筷子,等待右边筷子的时候,将会出现死锁。

All or Nothing

如果一个哲学家无法获取右侧的筷子,那么他会放下左侧的筷子

class Chopstick {

    // 其余代码相同

    public void pickUp() {
        lock.tryLock();
    }

}

class Philosopher extends Thread {

    public void eat() {
        if (pickUp()) {
            chew();
            putDown();
        }
    }

    public boolean pickUp() {
        if (!left.pickUp()) {
            return false;
        }

        if (!right.pickUp()) {
            left.putDown();
            return false;
        }

        return true;
    }

}

顺序访问

A lock in Java is owned by the same thread which locked it .

Semaphore

public class Foo {

    public Semaphore sem1, sem2;

    public Foo() {
        try {
            sem1 = new Semaphore(1);
            sem2 = new Semaphore(1);

            sem1.acquire();
            sem2.acquire();
        } catch (...) {
            ...
        }
    }

    public void first() {
        try {
            ...
            sem1.release();
        } catch (...) {
            ...
        }
    }

    public void second() {
        try {
            sem1.acquire();
            sem1.release();
            ...
            sem2.release();
        } catch (...) {
            ...
        }
    }

    public void third() {
        try {
            sem2.acquire();
            sem2.release();
            ...
        } catch (...) {
            ...
        }
    }

}