当前位置: 首页 > 知识库问答 >
问题:

另一个问题

杜英叡
2023-03-14

这是哲学家进餐问题的另一个实现,这是家庭作业问题,我将在这里展示我迄今为止所做的尝试:

/**
 * DPServer.java
 * <p>
 * This class implements the methods called by the philosophers
 */
package cc;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DPServer {

    private static Lock chopstick[] = new Lock[5]; // Create chopstick locks
    private static Lock mutex = new ReentrantLock(true);

    private static int MAX_EAT_TIME = 5000; // maximum eating time in milliseconds
    private static int MAX_THINK_TIME = 5000; // maximum thinking time in milliseconds
    private static Random r = new Random(0);


    // default constructor for DPServer class
    public DPServer() {
        for (int i = 0; i < 5; i++) {
            chopstick[i] = new ReentrantLock(true);
        } // end for

    } // end DPServer default constructor


    // called by a philosopher when they wish to eat
    public void takeChopsticks(int philosopherNumber) {
        // acquire chopstick[philosopherNumber] and chopstick[(philosopherNumber + 1) mod 5]
        System.out.println("Acquiring chopstick[" + philosopherNumber + "] and chopstick[" + ((philosopherNumber + 1) % 5) + "]");
        chopstick[philosopherNumber].lock();
        chopstick[(philosopherNumber + 1) % 5].lock();
        // eat for a random number of milliseconds
        int eatTime = r.nextInt(MAX_EAT_TIME);
        System.out.println("Philosopher " + philosopherNumber + " is eating for " + eatTime + " milliseconds");
        try {
            Thread.sleep(eatTime);
        } catch (InterruptedException ex) {
            System.out.println("Philosopher " + philosopherNumber + " eatTime sleep was interrupted");
        }

    } // end takeChopsticks


    // called by a philosopher when they are finished eating
    public void returnChopsticks(int philosopherNumber) {
        // release chopstick[philosopherNumber] and chopstick[(philosopherNumber + 1) mod 5]
        System.out.println("Releasing chopstick[" + philosopherNumber + "] and chopstick[" + ((philosopherNumber + 1) % 5) + "]");
        chopstick[(philosopherNumber + 1) % 5].unlock();
        chopstick[philosopherNumber].unlock();

        // think for a random number of milliseconds
        int thinkTime = r.nextInt(MAX_THINK_TIME);
        System.out.println("Philosopher " + philosopherNumber + " is thinking for " + thinkTime + " milliseconds");
        try {
            Thread.sleep(thinkTime);
        } catch (InterruptedException ex) {
            System.out.println("Philosopher " + philosopherNumber + " thinkTime sleep was interrupted");
        }
    }
}


// implementation of the Dining Philosopher class
package cc;

public class DPhilosopher {
    private int dpNum;
    private DPServer dpServ;

    // value constructor for the DPhilosopher class
    public DPhilosopher(int num, DPServer d) {
        dpNum = num;
        dpServ = d;
    } // end DPhilosopher value constructor


    public void DPEatThink() {
        while (true) {
            // get ready to eat
            System.out.println("Philosopher " + dpNum + " is getting ready to eat");
            dpServ.takeChopsticks(dpNum);

            // finish eating
            System.out.println("Philosopher " + dpNum + " is finished eating");
            dpServ.returnChopsticks(dpNum);

        }

    }

    public static void main(String[] args) {
        DPServer dps = new DPServer();
        DPhilosopher dp[] = new DPhilosopher[5];
        Thread dpThread[] = new Thread[5];

        // Create and launch the DPhilosopher threads
        for (int i = 0; i < 5; i++) {
            dp[i] = new DPhilosopher(i, dps);
            final int finalI = i;
            dpThread[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    dp[finalI].DPEatThink();
                }
            });
            dpThread[i].start();
        }

    } // end main
}

大部分的代码是准备好的,除了拿筷子()返回筷子()方法需要改变,我所做的就是添加这个:

chopstick[(philosopherNumber + 1) % 5].lock();
chopstick[philosopherNumber].lock();

chopstick[(philosopherNumber + 1) % 5].unlock();
chopstick[philosopherNumber].unlock();

我知道这不是线程安全的,这个链接也保证了这一点。真正的神话是老师希望我们使用DPServer#mutexlock来解决这个问题,我可以在takechoppesticks()returnchoppesticks()中锁定/解锁互斥锁,锁定和解锁两个锁(choppestick[philosopherNumber].lock();和筷子[(哲学家编号1)%5]。lock();),但这会造成僵局。

我只是不知道如何只用一个互斥重入锁来解决这个问题。

有人能帮我吗?

提前谢谢。

共有1个答案

寿伟
2023-03-14

如果在获取锁的周围放置锁,如下所示:

// called by a philosopher when they wish to eat
public void takeChopsticks(int philosopherNumber) {
    // acquire chopstick[philosopherNumber] and chopstick[(philosopherNumber + 1) mod 5]
    System.out.println("Acquiring chopstick[" + philosopherNumber + "] and chopstick[" + ((philosopherNumber + 1) % 5) + "]");

    lockLock.lock();
    chopstick[philosopherNumber].lock();
    chopstick[(philosopherNumber + 1) % 5].lock();
    lockLock.unlock();

    // eat for a random number of milliseconds
    int eatTime = r.nextInt(MAX_EAT_TIME);
    System.out.println("Philosopher " + philosopherNumber + " is eating for " + eatTime + " milliseconds");
    try {
        Thread.sleep(eatTime);
    } catch (InterruptedException ex) {
        System.out.println("Philosopher " + philosopherNumber + " eatTime sleep was interrupted");
    }

} // end takeChopsticks

那么,一次只能有一位哲学家在拿起筷子,但其他一切都如预期的那样继续工作。

另一个选择是改变筷子的索引,这样奇数哲学家总是从拿起左边的筷子开始,偶数哲学家总是从拿起右边的筷子开始。由于这是一个家庭作业,我将把如何做的细节留作练习(其实没那么难,一个if-else语句让它非常简单)。

 类似资料:
  • 尝试从同一命名空间中的另一个服务连接到一个服务。使用ClusterIP创建服务。创建服务后使用该Ip访问服务。请求有时成功,有时失败,我看到两个pod都启动并运行。以下是服务配置

  • 问题内容: 我有以下课程: 我有 为什么以下原因导致错误: 有任何想法吗? 问题答案: 对Java泛型的引用很好(jdk site )。 确实,@ Oli_Charlesworth提供了一个很好的答案,但也许这个答案会更完整。 在中,您不能插入任何正确的内容。 如果你有 和 然后,是两者的超类型: 因此写一些像这样的声明是合法的 这确实是通配符表示法存在的原因。 但是,这里的事情变得越来越有趣:

  • 我用Java重写了我的第一个程序,现在它看起来像这样: 实际上一切都很顺利,除了: > 当我在输入a、B和C的值时输入一个非数字类型时,会显示一个双重警告,然后它就会正常工作。(仅1个警告) 当我回答Y或N时,程序终止,但如果我输入任何其他内容,如“g”、“2”或“w”等,程序会再次询问我(第一次也是两次),然后当我输入Y或N,它工作得很好。 我真的不知道这是怎么回事,因为在编译过程中没有警告或错

  • 我知道Apache Cassandra的这种问题已经有一段时间了,例如:Pentaho帧大小(17727647)大于最大长度(16384000)!和thrift _ max _ message _ length _ in _ MB未识别卡桑德拉 但是我的问题有点不同。我使用Cassandra v2.0.7,我想将Pentaho Kettle(5.1)的数据插入Cassandra。我必须启用加密(S

  • 下面是fiddle http://jsfiddle.net/sgtrx/中的代码(应该在早些时候完成,对不起) 好的,我的导航栏在Div包装器内,在标题下,在内容区域(主体)的顶部。 我是个新手,所以请原谅我可能犯的任何错误。 当我添加边框来分隔每个块(按钮或文本)时,它很好地分隔了按钮,然而,它在导航栏的末尾(右侧)留下了一个小空格。 包装器Div是1000px,我有5个按钮,每个200px,因