2

以下のコードをコンパイルしてOSXで実行すると、「バーテンダー」スレッドsem_wait()がランダムな方法でスキップされ、Linuxマシンでコンパイルして実行するとsem_wait()、相対的なsem_post()予想どおり、への呼び出しが行われますか?

私は現在、POSIX スレッドだけでなく、並行処理全体についても学んでいるので、どんなコメント、ヒント、洞察も大歓迎です...

前もって感謝します。

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>

//using namespace std;

#define NSTUDENTS 30
#define MAX_SERVINGS 100

void* student(void* ptr);
void get_serving(int id);
void drink_and_think();

void* bartender(void* ptr);
void refill_barrel();


// This shared variable gives the number of servings currently in the barrel
int servings = 10;

// Define here your semaphores and any other shared data
sem_t *mutex_stu;
sem_t *mutex_bar;

int main() {
    static const char *semname1 = "Semaphore1";
    static const char *semname2 = "Semaphore2";

    pthread_t tid;

    mutex_stu = sem_open(semname1, O_CREAT, 0777, 0);
    if (mutex_stu == SEM_FAILED)
    {
        fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
        exit(EXIT_FAILURE);
    }
    mutex_bar = sem_open(semname2, O_CREAT, 0777, 1);
   if (mutex_bar == SEM_FAILED)
    {
        fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
        exit(EXIT_FAILURE);
    }

    pthread_create(&tid, NULL, bartender, &tid);
    for(int i=0; i < NSTUDENTS; ++i) {
        pthread_create(&tid, NULL, student, &tid);
    }

    pthread_join(tid, NULL);

    sem_unlink(semname1);
    sem_unlink(semname2);

    printf("Exiting the program...\n");
}


//Called by a student process. Do not modify this.
void drink_and_think() {
    // Sleep time in milliseconds
    int st = rand() % 10;
    sleep(st);
}

// Called by a student process. Do not modify this.
void get_serving(int id) {
    if (servings > 0) {
        servings -= 1;
    } else {
        servings = 0;
    }
    printf("ID %d got a serving. %d left\n", id, servings);
}

// Called by the bartender process.
void refill_barrel()
{
    servings = 1 + rand() % 10;
    printf("Barrel refilled up to -> %d\n", servings);
}

//-- Implement a synchronized version of the student
void* student(void* ptr) {
    int id = *(int*)ptr;
    printf("Started student %d\n", id);
    while(1) {
        sem_wait(mutex_stu);
        if(servings > 0) {
            get_serving(id);
        } else {
            sem_post(mutex_bar);
            continue;
        }
        sem_post(mutex_stu);
        drink_and_think();
    }
    return NULL;
}

//-- Implement a synchronized version of the bartender
void* bartender(void* ptr) {
    int id = *(int*)ptr;
    printf("Started bartender %d\n", id);
    //sleep(5);
    while(1) {
        sem_wait(mutex_bar);
        if(servings <= 0) {
            refill_barrel();
        } else {
            printf("Bar skipped sem_wait()!\n");
        }
        sem_post(mutex_stu);
    }
    return NULL;
}
4

1 に答える 1

2

プログラムを初めて実行すると、初期値を持つ名前付きセマフォが作成されますが、スレッドが終了しない (無限ループである) ため、sem_unlinkこれらのセマフォを削除する呼び出しに到達することはありません。プログラムを (ctrl-C またはその他の方法で) 強制終了すると、セマフォはどのような状態でも存在します。したがって、プログラムを再度実行すると、sem_open呼び出しは成功します (を使用しないためO_EXCL)。セマフォの値や状態をリセットしないため、奇妙な状態になる可能性があります。

sem_unlinkしたがって、 を呼び出す前に、プログラムの開始時に必ず呼び出す必要がありますsem_open。さらに良いことに、名前付きセマフォをまったく使用しないでくださいsem_init。代わりに、いくつかの名前のないセマフォを初期化するために使用してください。

于 2013-08-21T04:42:31.670 に答える