2015-11-08 53 views
0

我正在做一个家庭作业,我必须在C中编写一个多线程的Linux程序来解决操作系统类的生产者 - 消费者问题。在我的代码中,我有一个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

回答

0

您的问题是在下面的行

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++; 
} 
+0

请问'打破;'语句跳过'调用pthread_mutex_unlock(互斥);'和导致死锁? – Steven

+0

你是对的,更新为使用RAII – acgull

+0

删除'break;'语句并将'if'块留空可防止死锁?我不太了解RAII,并且不习惯使用它。 – Steven

2

该问题是由于线程在进入while循环后等待互斥造成的。你需要进入临界代码后,再次检查条件:

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

pthread_mutex_unlock(&mutex); 
-1
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); 
}