Linux pthread_cond_wait 为 2 个线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13675132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:56:30  来源:igfitidea点击:

pthread_cond_wait for 2 threads

clinuxpthreads

提问by eddie-ryan

I'm trying to implement pthread_cond_waitfor 2 threads. My test code is trying to use two threads to preform the following scenario:

我正在尝试实现pthread_cond_wait2 个线程。我的测试代码试图使用两个线程来执行以下场景:

  • Thread B waits for condition
  • Thread A prints "Hello" five times
  • Thread A signals thread B
  • Thread A waits
  • Thread B prints "Goodbye"
  • Thread B signals thread A
  • Loop to start (x5)
  • 线程 B 等待条件
  • 线程 A 打印“Hello”五次
  • 线程 A 向线程 B 发出信号
  • 线程 A 等待
  • 线程 B 打印“再见”
  • 线程 B 向线程 A 发出信号
  • 循环开始 (x5)

So far the code prints "Hello" five times and then gets stuck. From examples I've looked at it seems I'm on the right track, "Lock mutex, wait, get signaled by other thread, unlock mutex, do stuff, loop"

到目前为止,代码打印了五次“Hello”,然后卡住了。从我看过的例子来看,我似乎走在正确的轨道上,“锁定互斥锁,等待,其他线程发出信号,解锁互斥锁,做事,循环”

Test Code:

测试代码:

//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);
}

A pointer in the right direction would be greatly appreciated, thanks! (Code compiled on Linux using "gcc timeTest.c -o timeTest -lpthread")

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

采纳答案by caf

You have two problems. The first is that you aren't using while()loops correctly - for example, here:

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

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

i++;

The body of the whileloop is the statement i++- this will execute pthread_cond_wait()and i++until the pthread_cond_wait()returns an error, so this is essentially an endless loop.

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

The second is that you can't use a pthreads condition variable on its own - it needs to be paired with some actual shared state (at its simplest, this shared state might just be a flag variable protected by a mutex). The pthread_cond_wait()function is used to wait for the shared state to reach a certain value, and the pthread_cond_signal()function is used when a thread has altered the shared state. Reworking your example to use such a variable:

第二个是你不能单独使用 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;
}

Note that the use of two condition variables condAand condBis unnecessary here - the code would be just as correct if only one condition variable was used instead.

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

回答by d9ngle

The code actually works almostfine on my machine when you add curly braces to the while loop.

当您将花括号添加到 while 循环时,该代码实际上在我的机器上几乎可以正常工作。

Adding to what caf said, you'll enter an infinite loop when threadB is started after threadA has already sent the condB signal hence why you need to use a shared state in your while loop.

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

You can introduce artifical delay using usleep(1)on line 47 and see for yourself.

您可以使用usleep(1)第 47 行引入人为延迟并亲自查看。