我實際上正在做一個個人專案,我必須制作一個模擬這種行為的小程式:
有兩種型別的人:村民和德魯伊(如 Asterix/Obelix)
每個 VILLAGER 都由一個 id(村民唯一的數字)標識。它會在離開戰場前戰斗“nb_fights”時間。每次戰斗前,它必須從罐子里取出一份魔法藥水(如果罐子是空的,它必須通知德魯伊并等待罐子重新裝滿)。
DRUID 將等待村民召喚;然后它將用 pot_size 份重新裝滿鍋。當 nb_refills 完成后,druid 的原料已經用完,它的執行緒必須停止。
一切都在引數中給出(./panoramix <nb_villagers> <pot_size> <nb_fights> <nb_refills>)
好吧,實際上我完成了 70% 的專案,但我無法打電話給德魯伊補充藥水。
有村民執行緒的代碼:
void *villager(void *args)
{
int pNb = nbF;
int id = *(int *)args;
printf("Villager %d: Going into battle!\n", id);
while (pNb > 0) {
pthread_mutex_lock(&mpot);
printf("Villager %d: I need a drink... I see %d servings left.\n", id, pot_size);
if (pot_size == 0) {
printf("Villager %d: Hey Pano wake up! We need more potion.\n", id);
sem_wait(&test);
}
pot_size--;
pthread_mutex_unlock(&mpot);
pNb--;
printf("Villager %d: Take that roman scum! Only %d left.\n", id, pNb);
}
printf("Villager %d: I’m going to sleep now.\n", id);
}
WITH pNb = 戰斗次數(我們減少)
然后是德魯伊執行緒:
void *druid(void *args)
{
int sizepot = pot_size;
printf("Druid: I'm ready... but sleepy...\n");
while (nb_refills > 0) {
while (pot_size != 0) {
}
sem_wait(&test);
nb_refills--;
printf("Druid: Ah! Yes, yes, I'm awake! Working on it! Beware I can only make %d more refills after this one.\n", nb_refills);
pot_size = sizepot;
sem_post(&test);
}
printf("Druid: I'm out of viscum. I'm going back to... zZz\n");
}
我想知道當“pot_size”為空(=0)時如何“呼叫”德魯伊。
我嘗試在 if 條件下使用信號量來做到這一點:
if (pot_size == 0) {
printf("Villager %d: Hey Pano wake up! We need more potion.\n", id);
sem_wait(&test);
}
(等待德魯伊填充 pot_size 然后繼續程式)但我認為這不是很好。
編輯:整個代碼:
#include "struct.h"
sem_t test;
pthread_mutex_t mpot;
pthread_mutex_t fill;
int nbV = 0;
int pot_size = 0;
int nbF = 0;
int nb_refills = 0;
int errorhandler(int ac, char **av)
{
if (ac != 5)
{
printf("USAGE: ./panoramix <nb_villagers> <pot_size> <nb_fights> <nb_refills> \nValues must be > 0.\n");
return (84);
}
if (atoi(av[1]) == 0 || atoi(av[2]) == 0 || atoi(av[3]) == 0 || atoi(av[4]) == 0)
{
printf("USAGE: ./panoramix <nb_villagers> <pot_size> <nb_fights> <nb_refills> \nValues must be > 0.\n");
return (84);
}
return (0);
}
void *druid(void *args)
{
int sizepot = pot_size;
printf("Druid: I'm ready... but sleepy...\n");
while (nb_refills > 0) {
while (pot_size != 0) {
usleep(1000);
}
pthread_mutex_lock(&fill);
nb_refills--;
printf("Druid: Ah! Yes, yes, I'm awake! Working on it! Beware I can only make %d more refills after this one.\n", nb_refills);
pot_size = sizepot;
pthread_mutex_unlock(&fill);
}
printf("Druid: I'm out of viscum. I'm going back to... zZz\n");
}
void *villager(void *args)
{
int pNb = nbF;
int id = *(int *)args;
printf("Villager %d: Going into battle!\n", id);
while (pNb > 0) {
pthread_mutex_lock(&mpot);
printf("Villager %d: I need a drink... I see %d servings left.\n", id, pot_size);
if (pot_size == 0) {
printf("Villager %d: Hey Pano wake up! We need more potion.\n", id);
}
pot_size--;
pthread_mutex_unlock(&mpot);
pNb--;
printf("Villager %d: Take that roman scum! Only %d left.\n", id, pNb);
}
printf("Villager %d: I’m going to sleep now.\n", id);
}
int main(int ac, char **av)
{
if (errorhandler(ac, av) == 84)
return (84);
nbV = atoi(av[1]);
pot_size = atoi(av[2]);
nbF = atoi(av[3]);
nb_refills = atoi(av[4]);
pthread_t th[nbV];
int i;
pthread_mutex_init(&mpot, NULL);
pthread_mutex_init(&fill, NULL);
sem_init(&test, 0, 1);
for (int i = 0; i < nbV; i ) {
int *a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &villager, a) != 0) {
perror("Failed to create the Villager\n");
}
}
pthread_create(&th[nbV], NULL, &druid, NULL);
for (int i = 0; i < atoi(av[1]); i ) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to launch the Villager\n");
}
}
sem_destroy(&test);
pthread_mutex_destroy(&mpot);
pthread_mutex_destroy(&fill);
return (0);
}
uj5u.com熱心網友回復:
- 將游戲所需的所有全域變數分組到一個
struct中,在某個位置訪問它們變得更容易。
typedef struct {
int nbV; // # of villagers
int nbF; // # of fights each villager takes on
int nb_refills; // # of potion refills that druid can make
int pot_size; // size of potion pot
int potion_left; // remaining potion in pot for consumption
int druid_awake; // flag only modified by druid
int villagers_awake;
sem_t pot_sem;
pthread_mutex_t potion_mutex;
} sPanoramix_t;
sPanoramix_t pgame;
druid()不應該打電話sem_wait(),因為這是生產者。如果所有村民都打完了,檢查他們是否都睡著了,如果他們睡著了就回傳/退出。
void *druid (void *args) {
printf ("Druid: I'm ready... but sleepy...\n");
pgame.druid_awake = 1;
while (pgame.nb_refills > 0) {
while (pgame.potion_left > 0) {
if (!pgame.villagers_awake) {
printf ("Druid: KILLED all of them today! Drinks are on me :-)\n");
return NULL;
}
usleep (1000);
}
pgame.nb_refills--;
printf ("Druid: Ah! Yes, yes, I'm awake! Working on it! Beware I can only make %d more refills after this one.\n", pgame.nb_refills);
pgame.potion_left = pgame.pot_size;
printf ("Druid: Kill those romans, potion refilled to %d\n", pgame.potion_left);
sem_post (&pgame.pot_sem);
}
printf ("Druid: ALERT!! I'm out of viscum. I'm going back to... zZz\n");
pgame.druid_awake = 0; // druid is not available anymore
return NULL;
}
- 村民需要檢查德魯伊是否已經入睡,即。用盡所有補充配額。由于只有一個執行緒有互斥體并且沒有藥水可以消耗,我們可以阻止
sem_wait()德魯伊重新填充 &sem_post()。
void *villager (void *args) {
int pNb = pgame.nbF;
int id = (unsigned long)args;
printf ("Villager %d: Going into battle!\n", id);
while (pNb > 0) {
pthread_mutex_lock (&pgame.potion_mutex);
printf ("Villager %d: I need a drink... I see %d servings left.\n", id, pgame.potion_left);
if (pgame.potion_left <= 0) {
if (!pgame.druid_awake) {
printf ("Villager %d: We're doomed now Pano!\n", id);
pthread_mutex_unlock (&pgame.potion_mutex);
return NULL;
}
printf ("Villager %d: Hey Pano wake up! We need more potion.\n", id);
sem_wait (&pgame.pot_sem);
printf ("Villager %d: Thank you PANO!\n", id);
}
pgame.potion_left--;
pthread_mutex_unlock (&pgame.potion_mutex);
pNb--;
printf ("Villager %d: Take that Roman scum! Only %d left.\n", id, pNb);
usleep (1000); // let other villagers take turn
}
printf ("Villager %d: KILLED my quota of Romans, I’m going to sleep now.\n", id);
pthread_mutex_lock (&pgame.potion_mutex);
pgame.villagers_awake --;
pthread_mutex_unlock (&pgame.potion_mutex);
return NULL;
}
- 修改
main():
int main (int ac, char **av) {
if (errorhandler (ac, av) == 84)
return (84);
pgame.nbV = atoi (av[1]);
pgame.villagers_awake = pgame.nbV;
pgame.pot_size = atoi (av[2]);
pgame.potion_left = pgame.pot_size;
pgame.nbF = atoi (av[3]);
pgame.nb_refills = atoi (av[4]);
pthread_t th[pgame.nbV 1];
pthread_mutex_init (&pgame.potion_mutex, NULL);
sem_init (&pgame.pot_sem, 0, 1);
pthread_create (&th[0], NULL, druid, NULL);
usleep (1000);
for (int i = 1; i <= pgame.nbV; i ) {
if (pthread_create (&th[i], NULL, villager, (void*) (unsigned long)i) != 0)
perror ("Failed to create the Villager\n");
}
for (int i = 0; i <= pgame.nbV; i ) {
if (pthread_join (th[i], NULL) != 0)
perror ("Failed pthread_join()\n");
}
sem_destroy (&pgame.pot_sem);
pthread_mutex_destroy (&pgame.potion_mutex);
printf ("End of game Panoramix!\n");
return (0);
}
使用
strtol()而不是atoi(),它給你更多的控制權:如何在 C 中將字串轉換為整數?pthread_detach()如果執行緒沒有向等待它們的執行緒回傳任何有意義的內容,則可以使用pthread_join().
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/464201.html
上一篇:代碼塊輸出不同于在線編譯器
