首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将共享变量与两个信号量同步?

如何将共享变量与两个信号量同步?
EN

Stack Overflow用户
提问于 2021-12-08 20:27:38
回答 1查看 87关注 0票数 0

我有一个锻炼,在那里我有一个盛宴,从人N= 10,吃1份从锅中一次。锅有最大份量M= 5。也有一个厨师谁填补锅是空的servingsAvailable = 0。人在灌装的时候不能吃东西。我只能同步Pot类中的方法fill和getServings的线程(这些方法在开始时是空的)。

你能告诉我我在这段代码里做错了什么吗?总数应该是1000,但总是少一些。我达到的情况是,锅是填充然后5人吃,然后它的灌装等,但吃的数量是不一致的。

人类

代码语言:javascript
复制
public class Person extends Thread { // Reprezentuje tubylca
    Pot pot;
    int servingsConsumed = 0;
    public Person(String name, Pot pot) {
        super(name);
        this.pot = pot;
    }
    @Override
    public void run() {
        try {
            for (int i = 0; i < 100; ++i) {
                pot.getServing(this.getName());
                ++servingsConsumed;
                Thread.yield();
            }
        } catch(InterruptedException e) {
            return ;
        }
    }
}

厨艺班

代码语言:javascript
复制
public class Cook extends Thread { // Reprezentuje kucharza
    Pot pot;
    public Cook(Pot pot) {
        this.pot = pot;
        setDaemon(true);
    }
    @Override
    public void run() {
        try {
            while(!isInterrupted()) {
                pot.fill();
            }
        } catch(InterruptedException e) {
            return ;
        }
    }
}

Pot.class

代码语言:javascript
复制
import java.util.concurrent.Semaphore;

public class Pot {
    static final int M = 5; // Pojemność kotła
    private Semaphore emptyPot = new Semaphore(1);
    private Semaphore available = new Semaphore(0);
    private int servingsAvailable = 0;
    private int totalServedCount = 0;

    private synchronized void insertServings(int value) {
        servingsAvailable = value;
    }

    private synchronized int removeServing() {
        --servingsAvailable;
        ++totalServedCount;
        return servingsAvailable;
    }

    public int getTotalServedCount() {
        return totalServedCount;
    }

    public void getServing(String nameOfPerson) throws InterruptedException {
        available.acquire();
        if (servingsAvailable != 0) {
            removeServing();
            System.out.println(nameOfPerson + " ate 1 portion from pot");
        }
        available.release();
    }

    public void fill() throws InterruptedException {
        available.acquire();
        if (servingsAvailable == 0) {
            insertServings(M);
            System.out.println("Fill the pot with M = " + M);
        }
        available.release();
    }
}

宴席班(主)

代码语言:javascript
复制
public class Feast {
    public static void main(String[] args) throws InterruptedException {
        Pot pot = new Pot();
        Cook cook = new Cook(pot);
        final int N = 10;
        Person[] people = new Person[N];
        for (int i = 0; i < people.length; ++i) {
            people[i] = new Person("Person " + i, pot);
        }
        cook.start();
        for (Thread t : people) {
            t.start();
        }
        for (Thread t : people) {
            t.join();
        }
        cook.interrupt();
        System.out.printf("Total served: %d.\n", pot.getTotalServedCount());
        for (Person p : people) {
            System.out.printf("[%s] Ate %d servings.\n", p.getName(), p.servingsConsumed);
        }
        System.out.println("Finishing simulation.");
    }
}

到目前为止,我所取得的成果是:

我认为这里应该显示1000,而不是245。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-08 21:12:11

您使用信号量就像一个简单的互斥对象,没有任何方法让呼叫者知道有多少服务可用。如果你想发出信号通知罐子的状态,你应该在食物被填满和消耗的时候更新它们:

代码语言:javascript
复制
public void getServing(String nameOfPerson) throws InterruptedException {
    // take a permit and keep it
    available.acquire();
    System.out.println(nameOfPerson + " ate 1 portion from pot");
    if (removeServing() == 0) {
        // release a refill permit to the Cook
        emptyPot.release();
    }
}

public void fill() throws InterruptedException {
    // wait till pot is empty
    emptyPot.acquire();
    insertServings(M);
    System.out.println("Fill the pot with M = " + M);
    // release a permit for each serving
    available.release(M);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70281320

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档