12

私は、 を通じて公正および非公正な規律をテストされましRentrantLockた。食事の哲学者をシミュレートする小さなプログラムを書きました。

各哲学者には、s である左右のフォークがありますReentrantLock。私は1000回の思考と食事の行為をシミュレートしました:

 for (int i = 0; i < ACT_TIMES; i++) {
            act();
        }

どこactですか

private void act() {
        think();
        eat();

    }

Think面白くありません。しばらくスリープするだけです。ここにeat方法があります

private void eat() {
        try {
            if (left.tryLock(0, TimeUnit.MILLISECONDS)) {
                if (right.tryLock(0, TimeUnit.MILLISECONDS)) {
                    log("eating");
                    eatCount++;
                    try {
                        Thread.sleep(EAT_TIME);
                    } catch (InterruptedException e) {
                    } finally {
                        left.unlock();
                        right.unlock();
                    }
                } else {
                    left.unlock();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

主な方法:

 Lock[] forks = new Lock[5];
        for (int i = 0; i < forks.length; i++) {
            forks[i] = new ReentrantLock();
        }
        Philosopher p1 = new Philosopher(0, forks[1], forks[0]);
        Philosopher p2 = new Philosopher(1, forks[2], forks[1]);
        Philosopher p3 = new Philosopher(2, forks[3], forks[2]);
        Philosopher p4 = new Philosopher(3, forks[4], forks[3]);
        Philosopher p5 = new Philosopher(4, forks[0], forks[4]);
        ExecutorService exec = Executors.newFixedThreadPool(5);
        exec.submit(p1);
        exec.submit(p2);
        exec.submit(p3);
        exec.submit(p4);
        exec.submit(p5);

5 つのスレッドがすべて終了したら、哲学者ごとに eatCount を出力します。new ReentrantLock(true)そして、これらの値は、fair( ) と unfair( new ReentrantLock()) の規律でそれほど違いはありません。

(最初の数字は哲学者の数字です)

フェアロック:

0 344
1 348
2 366
3 359
4 363
Total number of eating 1780

不公平なロック:

0 338
1 338
2 339
3 341
4 352
Total number of eating 1708

私は、不公平なロックのために飢餓が発生することを予想していました。つまり、何人かの哲学者/哲学者は他の人よりもはるかに多くの eatCount を持たなければなりませんでしたが、飢餓は起こりませんでした。なぜ?

4

3 に答える 3

23

ロックを解放するスレッドは、他のスレッドがブロックされる可能性がある間ビジーであるため、ロックを取り戻す可能性がはるかに高くなります。各スレッドがロックを取得する可能性が等しいため、ビジー待機はこれを示しません。ひょっとしたら、ロックを解除する方が少し不利かもしれません。

final ReentrantLock lock = new ReentrantLock();
for (int i = 0; i < 5; i++) {
    final int finalI = i;
    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5; j++) {
                lock.lock();
                System.out.println("locked by " + finalI);
                lock.unlock();
            }
        }
    }).start();
}

版画

locked by 0
locked by 0
locked by 0
locked by 0
locked by 0
locked by 1
locked by 1
locked by 1
locked by 1
locked by 1
locked by 2
locked by 2
locked by 2
locked by 2
locked by 2
locked by 3
locked by 3
locked by 3
locked by 3
locked by 3
locked by 4
locked by 4
locked by 4
locked by 4
locked by 4

しかし、ロックを true で公正にすると、わかります

locked by 0
locked by 1
locked by 2
locked by 3
locked by 4
locked by 0
locked by 1
locked by 2
locked by 3
locked by 4
locked by 0
locked by 1
locked by 2
locked by 3
locked by 4
locked by 0
locked by 1
locked by 2
locked by 3
locked by 4
locked by 0
locked by 1
locked by 2
locked by 3
locked by 4
于 2012-12-17T17:32:07.653 に答える
1

すべて削除するsleep()と、多少の不公平が見られる場合があります。

于 2012-12-17T17:27:18.970 に答える