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

java中使用信号量的哲学家用餐

史和泰
2023-03-14

我想用java信号量解决用餐哲学家的问题,但我被卡住了。最高ID的筷子应该是可用的,但它似乎总是采取,我不知道为什么。谁能告诉我我错在哪里了?

Fork类:

class Fork {
public static Semaphore fork = new Semaphore(1);
public int id;

Fork(int id) {
    this.id = id;
}

public int getId() {
    return id;
}

public boolean take() {
    return fork.tryAcquire();
}

public void putDown() {
    fork.release();
}}

哲学家班:

class Philosopher extends Thread {

private Fork fork_low;
private Fork fork_high;
private String name;

Philosopher(Fork fork_low, Fork fork_high, String name) {
    this.fork_low = fork_low;
    this.fork_high = fork_high;
    this.name = name;
}

public void run() {

    try {
        sleep(1000);
    } catch (InterruptedException ex) {
    }

    while (true) {
        eat();
    }
}

private void eat(){
    if(fork_low.take()){
        if(fork_high.take()){
            try {
                sleep(2000); // eating;
            } catch (InterruptedException ex) { }

            fork_high.putDown();
            fork_low.putDown();  

        }
        else{
            fork_low.putDown();
        }
    }
}}

主要内容:

public static void main(String[] args) {
    String[] names = {"Plato", "Aristotle", "Cicero", "Confucius", "Eratosthenes"};
    Fork[] fork = new Fork[5];
    Philosopher[] philosopher = new Philosopher[5];

    for (int i = 0; i < fork.length; i++) {
        fork[i] = new Fork(i);
    }

    for (int i = 0; i < philosopher.length; i++) {

        if (i != philosopher.length - 1) {
            philosopher[i] = new Philosopher(fork[i], fork[i+1], names[i]);
            philosopher[i].start();
        } else {
            philosopher[i] = new Philosopher(fork[0], fork[i], names[i]);
            philosopher[i].start();
        }
    }
}

共有2个答案

赵兴朝
2023-03-14

这是用C语言解释解决的同一个问题

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>  
//if not used then gives warning for sleep used

//semaphore are basically designed to share the resources
// here the sem_t is the data type for the semaphore
sem_t room;//counting semaphore bcoz here only one instance of room butchair has 4
sem_t spoon[5]; //this is binary semaphore since every spoon has its own instance


void * philosopher(void *);
void eat(int);
int main()
{
int i;
int a[5];
pthread_t tid[5];// threads here are refrence to philosophers or diners bcoz we will have multiple users dining
                  
sem_init(&room,0,4);  
//1.pointer to declared semaphore
//2.pshared which has 0,1 value that is if 0 ->shared between threads                        
//                                      if 1 ->shared between process
//3.value with whch u initalise the semaphore
for(i=0;i<5;i++){
    //5 binary semaphore each for individual spoon
    sem_init(&spoon[i],0,1);
}

for(i=0;i<5;i++){
    a[i]=i;//allow 5 to enter at a time and deadlock occurs so let 4 of them in
    pthread_create(&tid[i],NULL,philosopher,(void*)&a[i]);
  //1.thread id 2.NULL 3.function 4.what you want to pass to the new thread   
  //here we pass the address of philosophers number to function
}

for(i=0;i<5;i++){
    pthread_join(tid[i],NULL);
}
}

void * philosopher(void * num){
int phil=*(int *)num; //cast the number passed as void to integer
//put sem_wait on both semaphore room and spoon
sem_wait(&room);//checks if resource is available,if then allocates and blocks semaphore
// room is counting semaphore so any is alocated then it decrements the count of total semaphore and 
// if all are allocated then it blocks thread and places it on queue untill resource is freed
printf("\nPhilospher number %d has sat on dining table\n",phil);
  
  sem_wait(&spoon[phil]);
  sem_wait(&spoon[(phil+1)%5]);
  //spoon is binary so if value of semaphore is 1 it is changed to 0 which means semaphore is allocated and cannot be used
  
  eat(phil);
  sleep(2);
  printf("\nPhilosopher %d has finished eating\n",phil);
  //free the semaphores so others in thread can use resources
  //returns +ve value on freeing semaphore
  //for binary semaphore if queue is empty then change semaphore value to 1 if not empty then remove process from queue and 
  // get it ready for allocation
  sem_post(&spoon[(phil+1)%5]);
  sem_post(&spoon[phil]);
  sem_post(&room);
}   

void eat(int phil){
  printf("\nPhilosopher %d is eating now\n",phil);
}
申辉
2023-03-14

您有一个死锁,因为信号量在Fork类中是静态的,这相当于只有一个Fork可用。当您使信号量不是静态的(两个随机的哲学家同时运行)时,它可以完美地工作。

您可以观察在JDK的内置工具jvisualvm中工作的线程。

 类似资料:
  • 我必须用信号量来解决这个问题。在我的代码中,每一个哲学家都在拿一根筷子,其他人都在等待。 我在主函数中仍然有一些错误。你能告诉我怎么使用筷子吗?我是BACI的初学者。

  • 我的Java代码中有一个问题,它应该模拟pholosophers问题,如下所述:http://en.wikipedia.org/wiki/Dining_philosophers_problem我想输出所有哲学家的当前状态,每次他们中的一个吃饭或思考。输出应该是这样的:“OxOx(2)”,其中“X”表示哲学家在吃,“O”表示他在思考,“O”表示他在等筷子。括号中的数字表示状态已更改的哲学家的编号。我

  • 今天,我决定尝试解决哲学家吃饭的问题。所以我写下面的代码。但我认为这是不正确的,所以如果有人告诉我这是怎么回事,我会很高兴的。我使用fork作为锁(我只读取它们,因为我不把对它们的访问放在同步块中),我有一个扩展线程的类,它保留了它的两个锁。 我认为有些不对劲,因为第五位哲学家从不吃饭,第四位和第三位哲学家大多吃饭。提前感谢。

  • 我们有一个任务来说明这个问题的僵局。我们已经编写了所有代码,并且代码可以编译,但是当运行代码时,一位哲学家最终吃了东西。所以这不意味着死锁实际上不会发生吗? 这就是输出:输出

  • 我试图按照Rust文档中的示例进行操作。链接中的最终代码: 运行此命令将生成以下输出: 根据文献记载,哲学家应该能够同时吃饭。预期结果如下所示: 不幸的是,无论代码执行的频率有多高,这种情况都不会发生。 我目前正在Windows上使用,但问题也发生在生锈的操场上。你自己试试吧。

  • 本文向大家介绍餐饮哲学家问题(DPP),包括了餐饮哲学家问题(DPP)的使用技巧和注意事项,需要的朋友参考一下 餐饮哲学家的问题指出,有5位哲学家共享一张圆桌,他们交替吃饭和思考。每个哲学家都有一碗饭和5根筷子。哲学家需要左右筷子才能吃饭。饿了的哲学家只有在两把筷子都齐备的情况下才可以吃东西,否则哲学家放下筷子,重新开始思考。 餐饮哲学家是一个经典的同步问题,因为它演示了一大类并发控制问题。 餐饮