使用线程来模拟舞厅中的舞者。每个线程代表舞厅里穿着彩色裙子的人。舞厅里有一个主舞台。然而。只有三人一组的舞者才可以上主舞台。进入主舞台的第二个要求是,两名舞者必须穿红色的裙子,另一名舞者必须穿白色的裙子。
在下面的程序中,每个线程在生成后调用对应于其颜色的函数。即有红色裙子的线程调用红色函数,有白色裙子的线程调用白色函数。
你的任务是添加同步代码到红色和白色,这样他们阻塞,直到三个线程一起进入主舞台,然后函数应该返回。假设两个红色线程被红色线程阻塞,然后一个白色线程调用白色线程,第三个线程应该唤醒其他两个线程,它们都应该返回。
#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; }