我正在使用两个线程解决生产者/消费者问题。我想我做错了什么,因为它似乎每次都提供相同的串行输出。有什么问题?
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
sem_t empty, full, mutex;
int bound[5];
int a,b;
void *producer(void *arg) {
for (int i = 0; i < 15; i++) {
sem_wait(&empty);
sem_wait(&mutex);
printf("%d is produced\n", i);
sleep(1);
bound[(++a) % 5] = i;
sem_post(&mutex);
sem_post(&full);
}
}
void *consumer(void *arg) {
int consumed;
for (int i = 0; i < 15; i++) {
sem_wait(&full);
sem_wait(&mutex);
consumed = bound[(++b) % 5];
printf("%d is consumed\n",consumed);
sleep(1);
sem_post(&mutex);
sem_post(&empty);
}
}
void main() {
pthread_t prod, con;
sem_init(&mutex, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, 5);
pthread_create(&prod,NULL,producer,NULL);
pthread_create(&con,NULL,consumer,NULL);
pthread_join(prod,NULL);
pthread_join(con,NULL);
}
输出就像生产者先消费5次,然后消费者全部消费,然后生产者再次生产,重复:
0 is produced 1 is produced 2 is produced 3 is produced 4 is produced 0 is consumed 1 is consumed 2 is consumed 3 is consumed 4 is consumed 5 is produced
等等。
最佳答案
一些线程正在等待信号量的事实并不意味着一旦信号量的值变为非零它就一定会解除阻塞,即使它是当时唯一等待的线程。可能发生的事情之一是其他一些尚未等待的线程突袭并首先获取它。
例如,在您的代码中,生产者和消费者都向 mutex
信号量发送消息,然后循环并再次尝试获取它。除非被 other 信号量阻塞,否则一个线程完全有可能释放 mutex
然后重新获取它,而另一个线程不会在其间获取它。事实上,您的消费者和生产者似乎都以五个项目为一组进行操作——对应于 empty
和 full
信号量的计数——表明这是在事实上正在发生的事情。
如果将 sleep
调用移到线程函数的关键区域之外,我希望您能获得完美的交替。你应该这样做,否则每个线程只有一个小窗口,它可以在其中接管另一个线程。
此外,虽然您可能会发现完美交替并不那么令人惊讶,但当您实现了一个长于一个项目的生产队列时,它也有些奇怪。我的意思是,如果队列中只有一项,为什么还要排长队呢?
为了看到所用队列容量的更多变化,您应该改变生产者和消费者的时间。您可能希望使用比 sleep()
提供的更高分辨率的计时器来实现它,否则您的运行将花费不必要的时间。
关于c - 生产者消费者同步使用两个线程提供不正常的串行输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51861200/