2012-12-02 14 views
9

我试图为2个线程实现pthread_cond_wait。我的测试代码试图用两个线程瓶坯以下情形:2线程的pthread_cond_wait

  • 线程B等待条件
  • 线程A打印“Hello”五次
  • 线程A信号线程B
  • 线程A等待
  • 线程B打印 “再见”
  • 线程B信号线程A
  • 回路,开始(X5)

到目前为止,代码打印出“Hello”五次然后卡住了。从例子我看似乎我是在正确的轨道上“锁定互斥,等待,得到由另一个线程发出信号,解除互斥体,做的东西,循环”

测试代码:

//Import 
#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <unistd.h> 

//global variables 
pthread_cond_t  condA = PTHREAD_COND_INITIALIZER; 
pthread_cond_t  condB = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER; 




void *threadA() 
{ 
    int i = 0, rValue, loopNum; 

    while(i<5) 
    { 
     //unlock mutex 
     rValue = pthread_mutex_unlock(&mutex); 

     //do stuff 
     for(loopNum = 1; loopNum <= 5; loopNum++) 
      printf("Hello %d\n", loopNum); 

     //signal condition of thread b 
     rValue = pthread_cond_signal(&condB); 

     //lock mutex 
     rValue = pthread_mutex_lock(&mutex); 

     //wait for turn 
     while(pthread_cond_wait(&condA, &mutex) != 0) 

     i++; 
    } 

} 



void *threadB() 
{ 
    int n = 0, rValue; 

    while(n<5) 
    { 
     //lock mutex 
     rValue = pthread_mutex_lock(&mutex); 

     //wait for turn 
     while(pthread_cond_wait(&condB, &mutex) != 0) 

     //unlock mutex 
     rValue = pthread_mutex_unlock(&mutex); 

     //do stuff 
     printf("Goodbye"); 

     //signal condition a 
     rValue = pthread_cond_signal(&condA); 

     n++;   
    } 
} 




int main(int argc, char *argv[]) 
{ 
    //create our threads 
    pthread_t a, b; 

    pthread_create(&a, NULL, threadA, NULL); 
    pthread_create(&b, NULL, threadB, NULL); 

    pthread_join(a, NULL); 
    pthread_join(b,NULL); 
} 

一个指针在正确的方向将不胜感激,谢谢! (在Linux上使用“gcc timeTest.c -o timeTest -lpthread”编译的代码)

+0

不,这是不需要的,我主要是尝试变化,但正如你所说,这将是理想的只使用一个 –

回答

28

你有两个问题。第一个是你没有正确使用while()循环 - 例如,在这里:

//wait for turn 
while(pthread_cond_wait(&condA, &mutex) != 0) 

i++; 

while循环体是语句i++ - 这将执行pthread_cond_wait()i++直到pthread_cond_wait()返回一个错误,所以这本质上是一个无限循环。

第二个是你不能自己使用一个pthreads条件变量 - 它需要与一些实际的共享状态配对(最简单的,这个共享状态可能只是一个被互斥锁保护的标志变量) 。 pthread_cond_wait()函数用于等待共享状态达到某个值,当线程更改共享状态时使用pthread_cond_signal()函数。返工您的示例使用了这样的变量:

//global variables 
/* STATE_A = THREAD A runs next, STATE_B = THREAD B runs next */ 
enum { STATE_A, STATE_B } state = STATE_A; 
pthread_cond_t  condA = PTHREAD_COND_INITIALIZER; 
pthread_cond_t  condB = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER; 

void *threadA() 
{ 
    int i = 0, rValue, loopNum; 

    while(i<5) 
    { 
     /* Wait for state A */ 
     pthread_mutex_lock(&mutex); 
     while (state != STATE_A) 
      pthread_cond_wait(&condA, &mutex); 
     pthread_mutex_unlock(&mutex); 

     //do stuff 
     for(loopNum = 1; loopNum <= 5; loopNum++) 
      printf("Hello %d\n", loopNum); 

     /* Set state to B and wake up thread B */ 
     pthread_mutex_lock(&mutex); 
     state = STATE_B; 
     pthread_cond_signal(&condB); 
     pthread_mutex_unlock(&mutex); 

     i++; 
    } 

    return 0; 
} 

void *threadB() 
{ 
    int n = 0, rValue; 

    while(n<5) 
    { 
     /* Wait for state B */ 
     pthread_mutex_lock(&mutex); 
     while (state != STATE_B) 
      pthread_cond_wait(&condB, &mutex); 
     pthread_mutex_unlock(&mutex); 

     //do stuff 
     printf("Goodbye\n"); 

     /* Set state to A and wake up thread A */ 
     pthread_mutex_lock(&mutex); 
     state = STATE_A; 
     pthread_cond_signal(&condA); 
     pthread_mutex_unlock(&mutex); 

     n++; 
    } 

    return 0; 
} 

需要注意的是使用两个条件变量condAcondB是不必要在这里 - 如果使用的条件只有一个变量,而不是代码将是一样正确。

+4

啊,与while循环令人尴尬的错误!感谢关于使用共享状态的输入,我理解其使用背后的原因。关于单个条件变量的使用,我完全同意你的意思。非常感谢您的回复,为编写较大的项目编写代码,再次感谢您的详细回复! –

+1

1所述共享状态的很好的描述(通常称为“谓词”),该CVAR-MTX对被设计来管理。 – WhozCraig

0

代码实际上工作差不多当我在你的机器上添加大括号到while循环时。

添加到caf所说的,当threadA在已经发送condB信号之后启动threadB时,您将进入无限循环,因此您需要在while循环中使用共享状态。

您可以在第47行中引入使用usleep(1)的人工延迟,然后亲自查看。

相关问题