以下是示例消费者/生产者模型的代码:
int buffer[MAX];
int fill_ptr = 0;
int use_ptr = 0;
int count = 3;
void put(int value) {
buffer[fill_ptr] = value;
fill_ptr = (fill_ptr + 1) % MAX;
count++;
}
int get() {
int tmp = buffer[use_ptr];
use_ptr = (use_ptr + 1) % MAX;
count--;
return tmp;
}
cond_t empty, fill;
mutex_t mutex;
void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
pthread_mutex_lock(&mutex); // p1
while (count == MAX) // p2
pthread_cond_wait(&empty, &mutex); // p3
put(i);// p4
pthread_cond_signal(&fill); // p5
pthread_mutex_unlock(&mutex); // p6
}
}
void* consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
pthread_mutex_lock(&mutex); // c1
while (count == 0) // c2
pthread_cond_wait(&fill, &mutex); // c3
int tmp = get(); // c4
pthread_cond_signal(&empty); // c5
pthread_mutex_unlock(&mutex); // c6
printf("%d\n", tmp);
}
}
但是,我认为这里存在问题。假设MAX = 3,并且最初缓冲区已满(count = 3),则消费者可以执行get()
并向生产者发信号。在生成器收到信号后,它会唤醒并开始在缓冲区[0]中执行put()
并保持互斥锁。
假设生产者刚陷入put()
;那么即使剩下2个资源,消费者也不能继续(因为互斥体由生产者持有)。
我的理解是否正确?如果是这样,那是不公平的,因为剩下2个资源可以消耗。
答案 0 :(得分:1)
假设生产者刚陷入put();那么即使剩下2个资源,消费者也不能继续(因为互斥体由生产者持有)。
在持有互斥锁时,你绝不能做一些可能卡住的事情,而你的代码却没有。
答案 1 :(得分:1)
我的理解是否正确?
是和否。
是的,如果consumer
调用producer
和put
被卡住(例如进入无限循环),put
将被卡住是正确的。
但是,您不能假设there are 2 resources left
。在pthread_cond_signal
读取所有3个三元素之前,producer
不承诺consumer
执行。所有你能知道的是consumer
读取至少一个元素,但在生产者执行之前它可能读取2或甚至3。
不,这不是不公平的。它正是互斥体的用途,即确保只有一个线程可以访问共享资源。如果是的话,这是不公平的......
因此,确保持有互斥锁的线程不会卡住是非常重要的!这是你作为程序员的责任。
注意:在您的情况下,内部没有任何内容可能导致线程卡住。