如何将共享变量与两个信号量同步?
How to synchronize shared variable with two Semaphores?
我有一个练习,我有一个盛宴,其中 N = 10 个人一次从锅里吃 1 份。锅有最大份量 M = 5。还有一个厨师在锅空时填充锅 servingsAvailable = 0。填充期间不能进食。我必须同步线程,只从 Pot class 更改方法 fill 和 getServings(这些方法一开始是空的)。
你能告诉我我在这段代码中做错了什么吗?总金额应为 1000,但总是更少。我实现了锅装满然后5个人吃,然后装满等的情况,但是吃的份数不一致。
人class
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 ;
}
}
}
厨师class
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
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();
}
}
盛宴class(主)
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。
您将信号量用作简单的互斥量,调用者无法通过任何方式知道有多少服务可用。如果你想用信号通知锅的状态,你应该在食物被填满和消耗时更新它们:
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);
}
我有一个练习,我有一个盛宴,其中 N = 10 个人一次从锅里吃 1 份。锅有最大份量 M = 5。还有一个厨师在锅空时填充锅 servingsAvailable = 0。填充期间不能进食。我必须同步线程,只从 Pot class 更改方法 fill 和 getServings(这些方法一开始是空的)。
你能告诉我我在这段代码中做错了什么吗?总金额应为 1000,但总是更少。我实现了锅装满然后5个人吃,然后装满等的情况,但是吃的份数不一致。
人class
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 ;
}
}
}
厨师class
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
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();
}
}
盛宴class(主)
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.");
}
}
到目前为止我取得的结果:
您将信号量用作简单的互斥量,调用者无法通过任何方式知道有多少服务可用。如果你想用信号通知锅的状态,你应该在食物被填满和消耗时更新它们:
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);
}