如果你试图访问一个全局变量,这个互斥锁 "lock" 不应该吗?
Shouldn't this mutex "lock" if you are trying to access a global variable?
我下面的源代码完全按照预期工作。问题是我设法让它工作只是因为我使用了 print f 语句来找出代码的位置 "stuck"。我不明白为什么在内部 while 循环中互斥体必须被解锁而不是被使用它的函数锁定。如果不是很清楚,我很抱歉,但我自己理解起来有问题。
为了理智起见,我将把有问题的代码片段单独放在顶部,完整的源代码放在下面。
// if buffer is full, release mutex lock and check again
if (shared_count == NITEMS)
{
// Signal consumer thread and sleep
pthread_cond_signal(&bufferNotEmpty);
pthread_cond_wait(&bufferNotFull,&mutex);
pthread_mutex_unlock(&mutex);
break;
}
这里是完整的源代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NITEMS 10 // number of items in shared buffer
// shared variables
char shared_buffer[NITEMS]; // echo buffer
int shared_count; // item count
pthread_mutex_t mutex; // pthread mutex
pthread_cond_t bufferNotEmpty; // pthread condition variable for consumer thread
pthread_cond_t bufferNotFull; // pthread condition variable for producer thread
unsigned int prod_index = 0; // producer index into shared buffer
unsigned int cons_index = 0; // consumer index into shared buffer
// function prototypes
void * producer(void *arg);
void * consumer(void *arg);
int main()
{
pthread_t prod_tid, cons_tid1, cons_tid2;
// initialize pthread variables
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&bufferNotEmpty, NULL);
pthread_cond_init(&bufferNotFull, NULL);
// start producer thread
pthread_create(&prod_tid, NULL, producer, NULL);
// start consumer threads
pthread_create(&cons_tid1, NULL, consumer, NULL);
pthread_create(&cons_tid2, NULL, consumer, NULL);
// wait for threads to finish
pthread_join(prod_tid, NULL);
pthread_join(cons_tid1, NULL);
pthread_join(cons_tid2, NULL);
// clean up
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&bufferNotEmpty);
pthread_cond_destroy(&bufferNotFull);
return 0;
}
// producer thread executes this function
void * producer(void *arg)
{
char key;
while (1)
{
// read input key
scanf("%c", &key);
while (1)
{
// acquire mutex lock
pthread_mutex_lock(&mutex);
// if buffer is full, release mutex lock and check again
if (shared_count == NITEMS)
{
// Signal consumer thread and sleep
pthread_cond_signal(&bufferNotEmpty);
pthread_cond_wait(&bufferNotFull,&mutex);
pthread_mutex_unlock(&mutex);
break;
}
else
break;
}
// store key in shared buffer
shared_buffer[prod_index] = key;
// update shared count variable
shared_count++;
// update producer index
if (prod_index == NITEMS - 1)
prod_index = 0;
else
prod_index++;
// release mutex lock and signal consumer thread
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&bufferNotEmpty);
}
return NULL;
}
// consumer thread executes this function
void * consumer(void *arg)
{
char key;
int id = (int)pthread_self();
while (1)
{
while (1)
{
// acquire mutex lock
pthread_mutex_lock(&mutex);
// if buffer is empty, wake producer thread and sleep
if (shared_count == 0)
{
pthread_cond_signal(&bufferNotFull);
pthread_cond_wait(&bufferNotEmpty,&mutex);
pthread_mutex_unlock(&mutex);
}
else
break;
}
// read key from shared buffer
key = shared_buffer[cons_index];
// echo key
printf("consumer %d %c\n", id, key);
// update shared count variable
shared_count--;
// update consumer index
if (cons_index == NITEMS - 1)
cons_index = 0;
else
cons_index++;
// release mutex lock and signal producer thread
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&bufferNotFull);
}
return NULL;
}
您的等待模式有误。它是:
// acquire mutex lock
pthread_mutex_lock(&mutex);
// while buffer is empty, wait
while (shared_count == 0)
{
pthread_cond_wait(&bufferNotEmpty,&mutex);
}
// read key from shared buffer
key = shared_buffer[cons_index];
// echo key
printf("consumer %d %c\n", id, key);
// update shared count variable
shared_count--;
// update consumer index
if (cons_index == NITEMS - 1)
cons_index = 0;
else
cons_index++;
// release mutex lock and signal producer thread
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&bufferNotFull);
用同样的方法固定另一侧。您需要一个等待条件满足的循环,并且您希望在弄乱共享状态时保持(可能重新获取)互斥锁。
注意我删除了对 pthread_cond_signal
的第一个调用。无论 使 shared_count
等于零,都已经唤醒了另一个线程。我们还没有改变任何东西,所以我们还不需要告诉任何人。
如果您没有做任何需要通知的事情,通知另一个线程是没有意义的。当您需要告诉另一个线程您更改了它可能正在等待的某些共享状态时,您可以调用 pthread_cond_signal
。
Upon successful return, the mutex shall have been locked and shall be
owned by the calling thread
pthread_cond_wait()
将锁定互斥体,因此调用
pthread_cond_wait(&bufferNotEmpty,&mutex);
// mutex is already locked
pthread_mutex_lock(&mutex);
// deadlock
会导致死锁
我下面的源代码完全按照预期工作。问题是我设法让它工作只是因为我使用了 print f 语句来找出代码的位置 "stuck"。我不明白为什么在内部 while 循环中互斥体必须被解锁而不是被使用它的函数锁定。如果不是很清楚,我很抱歉,但我自己理解起来有问题。
为了理智起见,我将把有问题的代码片段单独放在顶部,完整的源代码放在下面。
// if buffer is full, release mutex lock and check again
if (shared_count == NITEMS)
{
// Signal consumer thread and sleep
pthread_cond_signal(&bufferNotEmpty);
pthread_cond_wait(&bufferNotFull,&mutex);
pthread_mutex_unlock(&mutex);
break;
}
这里是完整的源代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NITEMS 10 // number of items in shared buffer
// shared variables
char shared_buffer[NITEMS]; // echo buffer
int shared_count; // item count
pthread_mutex_t mutex; // pthread mutex
pthread_cond_t bufferNotEmpty; // pthread condition variable for consumer thread
pthread_cond_t bufferNotFull; // pthread condition variable for producer thread
unsigned int prod_index = 0; // producer index into shared buffer
unsigned int cons_index = 0; // consumer index into shared buffer
// function prototypes
void * producer(void *arg);
void * consumer(void *arg);
int main()
{
pthread_t prod_tid, cons_tid1, cons_tid2;
// initialize pthread variables
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&bufferNotEmpty, NULL);
pthread_cond_init(&bufferNotFull, NULL);
// start producer thread
pthread_create(&prod_tid, NULL, producer, NULL);
// start consumer threads
pthread_create(&cons_tid1, NULL, consumer, NULL);
pthread_create(&cons_tid2, NULL, consumer, NULL);
// wait for threads to finish
pthread_join(prod_tid, NULL);
pthread_join(cons_tid1, NULL);
pthread_join(cons_tid2, NULL);
// clean up
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&bufferNotEmpty);
pthread_cond_destroy(&bufferNotFull);
return 0;
}
// producer thread executes this function
void * producer(void *arg)
{
char key;
while (1)
{
// read input key
scanf("%c", &key);
while (1)
{
// acquire mutex lock
pthread_mutex_lock(&mutex);
// if buffer is full, release mutex lock and check again
if (shared_count == NITEMS)
{
// Signal consumer thread and sleep
pthread_cond_signal(&bufferNotEmpty);
pthread_cond_wait(&bufferNotFull,&mutex);
pthread_mutex_unlock(&mutex);
break;
}
else
break;
}
// store key in shared buffer
shared_buffer[prod_index] = key;
// update shared count variable
shared_count++;
// update producer index
if (prod_index == NITEMS - 1)
prod_index = 0;
else
prod_index++;
// release mutex lock and signal consumer thread
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&bufferNotEmpty);
}
return NULL;
}
// consumer thread executes this function
void * consumer(void *arg)
{
char key;
int id = (int)pthread_self();
while (1)
{
while (1)
{
// acquire mutex lock
pthread_mutex_lock(&mutex);
// if buffer is empty, wake producer thread and sleep
if (shared_count == 0)
{
pthread_cond_signal(&bufferNotFull);
pthread_cond_wait(&bufferNotEmpty,&mutex);
pthread_mutex_unlock(&mutex);
}
else
break;
}
// read key from shared buffer
key = shared_buffer[cons_index];
// echo key
printf("consumer %d %c\n", id, key);
// update shared count variable
shared_count--;
// update consumer index
if (cons_index == NITEMS - 1)
cons_index = 0;
else
cons_index++;
// release mutex lock and signal producer thread
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&bufferNotFull);
}
return NULL;
}
您的等待模式有误。它是:
// acquire mutex lock
pthread_mutex_lock(&mutex);
// while buffer is empty, wait
while (shared_count == 0)
{
pthread_cond_wait(&bufferNotEmpty,&mutex);
}
// read key from shared buffer
key = shared_buffer[cons_index];
// echo key
printf("consumer %d %c\n", id, key);
// update shared count variable
shared_count--;
// update consumer index
if (cons_index == NITEMS - 1)
cons_index = 0;
else
cons_index++;
// release mutex lock and signal producer thread
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&bufferNotFull);
用同样的方法固定另一侧。您需要一个等待条件满足的循环,并且您希望在弄乱共享状态时保持(可能重新获取)互斥锁。
注意我删除了对 pthread_cond_signal
的第一个调用。无论 使 shared_count
等于零,都已经唤醒了另一个线程。我们还没有改变任何东西,所以我们还不需要告诉任何人。
如果您没有做任何需要通知的事情,通知另一个线程是没有意义的。当您需要告诉另一个线程您更改了它可能正在等待的某些共享状态时,您可以调用 pthread_cond_signal
。
Upon successful return, the mutex shall have been locked and shall be owned by the calling thread
pthread_cond_wait()
将锁定互斥体,因此调用
pthread_cond_wait(&bufferNotEmpty,&mutex);
// mutex is already locked
pthread_mutex_lock(&mutex);
// deadlock
会导致死锁