多线程程序运行 while 循环额外次数

Multithreaded program runs while loop extra times

我正在做家庭作业,我必须用 C 语言编写一个多线程 linux 程序来解决操作系统 class 的生产者-消费者问题。在我的代码中,我有一个 while 循环,它位于函数 运行 内,由单个线程执行。在该函数中,我有一个变量的增量,该变量受 mutex.

保护

问题是,有时 while 循环 运行 的时间比我预期的要多。例如,当我希望循环执行 16 次时,它有时会执行 17 次。我无法弄清楚这个错误的原因,但它似乎与线程有关。我已经最小化了我的代码,问题仍然可以重现。

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

int numItems = 16;
pthread_t threadID;
pthread_t threadID2;

pthread_mutex_t mutex;

pthread_attr_t attr;


void *produce(void *param);

int numItemsProduced = 0;

int main(int argc, char *argv[])
{

    pthread_attr_init(&attr);
    // Initialize mutex.
    if (pthread_mutex_init(&mutex, NULL) != 0)
    {
        printf("%s\n", "An error occured while initializing mutex!");
    }

    pthread_create(&threadID, &attr, produce, NULL);

    pthread_create(&threadID2, &attr, produce, NULL);

    pthread_join(threadID, NULL);
    pthread_join(threadID2, NULL);


    printf("Finished.\n");
}


void *produce(void *param)
{
    printf("In thread.\n");
    while (numItemsProduced < numItems)
    {
        pthread_mutex_lock(&mutex);
        printf("Current while loop is at int %d\n", numItemsProduced);

        numItemsProduced++;

        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(0);
}

为什么while循环有时会执行额外的时间?我相信我正确使用了 mutex

问题是线程进入while循环后等待互斥锁引起的。输入关键代码后需要再次检查条件:

pthread_mutex_lock(&mutex);
if (numItemsProduced < numItems){
    printf("Current while loop is at int %d\n", numItemsProduced);
    numItemsProduced++;
}

pthread_mutex_unlock(&mutex);

您的问题在下一行

while (numItemsProduced < numItems)

这一行没有线程安全,因为您还没有锁定互斥锁。 您应该锁定互斥量以检查条件和更新值。

可以改写为:

while (1)
{
    pthread_mutex_lock(&mutex);
    if (numItemsProduced >= numItems)
    {
         pthread_mutex_unlock(&mutex);
         break;
    }
    printf("Current while loop is at int %d\n", numItemsProduced);

    numItemsProduced++;
    pthread_mutex_unlock(&mutex);
}

或者如果使用 c++:

struct LockGuard
{
     LockGuard(pthread_mutex_t* mutex) : _pmutex(mutex) 
     { 
         pthread_mutex_lock(_pmutex);
     };

     ~LockGuard() 
     { 
          pthread_mutex_unlock(_pmutex);
     }
   private:
     LockGuard(const LockGuard&); // or use c++0x ` = delete`

     pthread_mutex_t* _pmutex;
};

while (true)
{
    LockGuard(&mutex);
    if (numItemsProduced >= numItems)
    {
         break;
    }
    printf("Current while loop is at int %d\n", numItemsProduced);

    numItemsProduced++;
}
void *produce(void *param)
{
    printf("In thread.\n");
    while (1)
    {
        pthread_mutex_lock(&mutex);
        if(numItemsProduced >= numItems){
            pthread_mutex_unlock(&mutex);
            break;
        }
        printf("Current while loop is at int %d\n", numItemsProduced);

        numItemsProduced++;

        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(0);
}