线程同步那点事儿之semaphore+barrier的应用

使用线程来模拟舞厅中的舞者。每个线程代表舞厅里穿着彩色裙子的人。舞厅里有一个主舞台。然而。只有三人一组的舞者才可以上主舞台。进入主舞台的第二个要求是,两名舞者必须穿红色的裙子,另一名舞者必须穿白色的裙子。

在下面的程序中,每个线程在生成后调用对应于其颜色的函数。即有红色裙子的线程调用红色函数,有白色裙子的线程调用白色函数。

你的任务是添加同步代码到红色和白色,这样他们阻塞,直到三个线程一起进入主舞台,然后函数应该返回。假设两个红色线程被红色线程阻塞,然后一个白色线程调用白色线程,第三个线程应该唤醒其他两个线程,它们都应该返回。

#include <stdio.h>
#include <pthread.h>

#define NWHITE (1000)
#define NRED   (NWHITE * 2)

void read(void);
void white(void);

void* red(void *arg) {
    // TODO
    red();
    return NULL;
}

void* white(void *arg) {
    // TODO
    white();
    return NULL;
}

int main(void) {
    pthread_t thread_ids[NRED + NWHITE];

    for (size_t i = 0; i < NWHITE; ++i) {
        pthread_create(thread_ids + i * 3 + 0, NULL, red, NULL);
        pthread_create(thread_ids + i * 3 + 1, NULL, red, NULL);
        pthread_create(thread_ids + i * 3 + 2, NULL, white, NULL);
    }

    for (size_t i = 0; i < NRED + NWHITE; ++i) {
        pthread_join(thread_ids[i], NULL);
    }return 0;
}

利用信号量和barrier来实现:

实现后代码如下:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define NWHITE (1000)
#define NRED   (NWHITE * 2)

sem_t red_pairs;
sem_t white_mutex;
pthread_barrier_t stage;

void read(void);
void white(void);

void* red(void *arg) {

    // Using a semaphore that allows only two red threads to enter
    // Using a barrier to wait for the white thread to enter

    sem_wait(&red_pairs);
    pthread_barrier_wait(&stage);
    sem_post(&red_pairs);
    red();
    return NULL;
}

void* white(void *arg) {

    // Using a mutex that allows only one white thread to enter
    // Using a barrier to wait for the other two red threads

    sem_wait(&white_mutex);
    pthread_barrier_wait(&stage);
    sem_post(&white_mutex);
    white();
    return NULL;
}

int main(void) {

    sem_init(&red_pairs, 0, 2);
    sem_init(&white_mutex, 0, 1);
    pthread_barrier_init(&stage, NULL, 3);

    pthread_t thread_ids[NRED + NWHITE];

    for (size_t i = 0; i < NWHITE; ++i) {
        pthread_create(thread_ids + i * 3 + 0, NULL, red, NULL);
        pthread_create(thread_ids + i * 3 + 1, NULL, red, NULL);
        pthread_create(thread_ids + i * 3 + 2, NULL, white, NULL);
    }

    for (size_t i = 0; i < NRED + NWHITE; ++i) {
        pthread_join(thread_ids[i], NULL);
    }

    pthread_barrier_destroy(&stage);

    return 0;
}
posted @ 2021-06-20 07:38  山中水寒  阅读(98)  评论(0编辑  收藏  举报