方法在我不期望的地方被调用 [英] Method gets called where I don't expect it to

查看:79
本文介绍了方法在我不期望的地方被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个著名的Philosopher问题的多线程代码示例.在这种情况下,有5位哲学家尝试进餐,但他们与旁边的下一位哲学家共享同一叉子.

I have a multithreading code example for the well known Philosopher problem. In this scenario 5 Philosophers try to eat, but they share the same fork with the next Philosopher sitting next to them.

我在理解此代码中的线程工作方式时遇到问题:

I have a problem understanding the way a Thread in this code works:

当我观察到此代码的输出时,看起来pickupwait之后执行test.但是考虑到test明显早于wait,这怎么可能?

When I observe the output of this code, it looks like pickup executes test after wait. But how is that possible, considering test comes clearly before wait?

示例输出:

哲学0饿了
哲学0在吃东西
哲学家在吃饭:0.
哲学3饿了
哲学3正在进食
哲学家在吃饭:0 3.
哲学1饿了
哲学2饿了
哲学4饿了
哲学0在思考
哲学1在吃东西

Philosoph 0 is hungry
Philosoph 0 is eating
Philosophers eating: 0 .
Philosoph 3 is hungry
Philosoph 3 is eating
Philosophers eating: 0 3 .
Philosoph 1 is hungry
Philosoph 2 is hungry
Philosoph 4 is hungry
Philosoph 0 is thinking
Philosoph 1 is eating

哲学家1正在吃东西"由test(1)打印,被pickup(1)调用,但这怎么可能?

"Philosoph 1 is eating" gets printed by test(1), which is called by pickup(1), but how is that possible?

课堂哲学:

class Philosoph extends Thread {
    Dining_Philosophers dp;
    int name;

    public Philosoph(int n, Dining_Philosophers d) {
        name = n;
        dp = d;
    }

    public void run() {
        while (true) {
            thinking();
            dp.pickup(name);
            eating();
            dp.putdown(name);
        }
    }

    public static void main(String[] args) {
        Dining_Philosophers dp = new Dining_Philosophers();
        Philosoph p0 = new Philosoph(0, dp);
        Philosoph p1 = new Philosoph(1, dp);
        Philosoph p2 = new Philosoph(2, dp);
        Philosoph p3 = new Philosoph(3, dp);
        Philosoph p4 = new Philosoph(4, dp);
        p0.start();
        p1.start();
        p2.start();
        p3.start();
        p4.start();
    }

    void thinking() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
    }

    void eating() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
    }
}

进餐哲学家:

class Dining_Philosophers {
    static int thinking = 0;
    static int hungry = 1;
    static int eating = 2;
    int[] state = new int[5];

    public Dining_Philosophers() {
        for (int i = 0; i < 5; i++) {
            state[i] = thinking;
        }
    }

    public synchronized void pickup(int i) {
        //The Thread executes this function, but 
        // when it executes the wait function und wake up after the notification by another
        // thread then it executes only the test-function. But why only the it and not the  
        // other Code like the "System.out.println("Philosoph " + i + " is hungry");" ?
        state[i] = hungry;
        System.out.println("Philosoph " + i + " is hungry");
        test(i);
        while (state[i] != eating) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
    }

    public synchronized void putdown(int i) {
        state[i] = thinking;
        System.out.println("Philosoph " + i + " is thinking");
        test((i + 4) % 5);
        test((i + 1) % 5);
    }

    public void test(int k) {
        int i;
        if ((state[(k + 4) % 5] != eating) && (state[k] == hungry) && (state[(k + 1) % 5] != eating)) {
            state[k] = eating;
            System.out.println("Philosoph " + k + " is eating");
            System.out.print("Philosophers eating: ");
            for (i = 0; i < 5; i++)
                if (state[i] == eating)
                    System.out.print(i + " ");
            System.out.println(".");
            notifyAll();
        }
    }
}

推荐答案

您会丢失test不仅由pickup调用,而且由putdown调用.

You are missing that test is not only called by pickup, but also by putdown.

示例中的哲学家1正在吃东西" 输出不是pickup(1)调用的,而是putdown(0)调用的. putdown在哲学家之前和之后都呼叫test给哲学家.

The "Philosoph 1 is eating" output in your example wasn't called by pickup(1), but by putdown(0). putdown calls test for the philosopher before and after.

表达式(i + 4) % 5(i + 1) % 5可能有点令人困惑,但是(i + 4) % 5给出了以前的哲学家:

The expressions (i + 4) % 5 and (i + 1) % 5 might be a bit confusing, but (i + 4) % 5 gives the previous philosopher:

(0 + 4)%5 = 4
(1 + 4)%5 = 0
(2 + 4)%5 = 1
(3 + 4)%5 = 2
(4 + 4)%5 = 3

(0 + 4) % 5 = 4
(1 + 4) % 5 = 0
(2 + 4) % 5 = 1
(3 + 4) % 5 = 2
(4 + 4) % 5 = 3

(i + 1) % 5给出了下一个哲学家:

and (i + 1) % 5 gives the next philosopher:

(0 + 1)%5 = 1
(1 +1)%5 = 2
(2 +1)%5 = 3
(3 +1)%5 = 4
(4 +1)%5 = 0

(0 + 1) % 5 = 1
(1 + 1) % 5 = 2
(2 + 1) % 5 = 3
(3 + 1) % 5 = 4
(4 + 1) % 5 = 0

这篇关于方法在我不期望的地方被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆