不应该这个互斥锁"锁定"如果您尝试访问全局变量?

时间:2016-10-26 18:42:02

标签: c multithreading system mutex condition-variable

我的源代码完全按照预期的方式工作。问题是我设法让它工作只是因为我使用print f语句来找出代码所在的位置"卡住了#34;。我不明白为什么在内部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;
}

2 个答案:

答案 0 :(得分:4)

您的等待模式错误。它&#39; S:

    // 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

答案 1 :(得分:1)

  

成功返回后,互斥锁应已锁定且应为   由调用线程

拥有      

https://linux.die.net/man/3/pthread_cond_wait

pthread_cond_wait()会锁定互斥锁,因此请调用

pthread_cond_wait(&bufferNotEmpty,&mutex);
// mutex is already locked
pthread_mutex_lock(&mutex);
// deadlock

会导致死锁