POSIX C线程.pthread_cond_t例子.不能按预期工作

Jac*_*ieg 6 c++ variables pthreads multitasking conditional-statements

我写了一个写了一个程序,它没有像我期望的那样工作.我有两个线程:thread触发器funcanotherThread触发器anotherFunc.我想做的是当cont达到值10func,anotherThread使用pthread_cond_wait和触发pthread_cond_signal.奇怪的是,如果我取消注释,一切正常sleep(1).我是线程的新手,我在这里遵循教程,如果我sleep在他们的例子中评论该行,它也会中断.

我的问题是如何在没有任何sleep()电话的情况下完成这项工作?如果在我的代码中func达到pthread_mutex_lock之后会发生什么anotherFunc?我该如何控制这些东西?这是我的代码:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

pthread_mutex_t myMutex;
pthread_cond_t cond;
pthread_attr_t attr;

int cont;

void *func(void*)
{
    printf("func\n");

    for(int i = 0; i < 20; i++)
    {
        pthread_mutex_lock(&myMutex);

        cont++;
        printf("%d\n", cont);
        if(cont == 10)
        {
            printf("signal:\n");
            pthread_cond_signal(&cond);
//            sleep(1);
        }
        pthread_mutex_unlock(&myMutex);
    }
    printf("Done func\n");

    pthread_exit(NULL);
}

void *anotherFunc(void*)
{
    printf("anotherFunc\n");
    pthread_mutex_lock(&myMutex);
    printf("waiting...\n");

    pthread_cond_wait(&cond, &myMutex);
    cont += 10;
    printf("slot\n");

    pthread_mutex_unlock(&myMutex);
    printf("mutex unlocked anotherFunc\n");
    printf("Done anotherFunc\n");

    pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
    pthread_t thread;
    pthread_t anotherThread;

    pthread_attr_init(&attr);
    pthread_mutex_init(&myMutex, NULL);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_cond_init(&cond, NULL);

    pthread_create(&anotherThread, &attr, anotherFunc, NULL);
    pthread_create(&thread, &attr, func, NULL);

    pthread_join(thread, NULL);
    pthread_join(anotherThread, NULL);

    printf("Done MAIN()");

    pthread_mutex_destroy(&myMutex);
    pthread_cond_destroy(&cond);
    pthread_attr_destroy(&attr);


    pthread_exit(NULL);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

很抱歉这篇文章很长,但我是新手,我很乐意学习.你也知道关于Linux上线程和网络的一些好的参考资料或课程/教程吗?我想学习创建一个聊天客户端,我听说我必须知道线程和网络.问题是我不知道如果我学到的东西还不错,因为我不知道我必须知道什么.

非常感谢 :)

Kaz*_*Kaz 9

anotherThread只是在pthread_cond_wait没有先测试所需条件(计数器达到10)是否已经发生的情况下调用.这是不正确的逻辑,这将导致丢失的唤醒问题:一个反复出现错误的名称,它会困扰错误编写的多线程程序.

条件变量是无状态的.如果pthread_cond_signalpthread_cond_broadcast在没有线程当前正在等待的条件上调用,则该操作无效.它没有被记住.因此,您的信令线程可以10非常快速地计数,并在另一个线程到达pthread_cond_wait调用之前发出条件变量的信号.

你需要一个循环pthread_cond_wait.必须检查条件以防它已经为真,这样线程就不会等待已经发生的唤醒.它应该是一个循环,因为唤醒可能是虚假的:只是因为线程通过pthread_cond_wait并不意味着条件实际上是真的:

while (cont < 10)
  pthread_cond_wait(&cond, &myMutex);
Run Code Online (Sandbox Code Playgroud)

此外,不需要创建线程属性只是为了使线程可连接.当您为创建属性使用空指针时,这是默认情况.POSIX线程是可连接的,除非创建分离,或转换为分离pthread_detach.

另一件事:尽可能避免pthread_cond_signal在持有互斥锁时进行呼叫.这不是不正确的,但它可能是浪费的,因为操作实际上可能必须调用OS内核来唤醒一个线程,因此你在整个系统调用中持有这个昂贵的互斥锁(当你真正需要它时)保护在应用程序中使用共享数据的一些机器指令.