c++ - POSIX C 线程。 pthread_cond_t 示例。没有按预期工作

标签 c++ variables pthreads conditional-statements multitasking

我写了一个程序,但它没有像我预期的那样工作。 我有两个线程:thread 触发 funcanotherThread 触发 anotherFunc。我想做的是当 contfunc 中达到值 10 时,使用 触发 anotherThread pthread_cond_waitpthread_cond_signal。奇怪的是,如果我取消注释 sleep(1) 行,一切正常。我是线程的新手,我正在学习教程 here如果我在他们的示例中评论 sleep 行,它也会中断。

我的问题是如何在没有任何 sleep() 调用的情况下完成这项工作?如果在我的代码中 funcanotherFunc 之后到达 pthread_mutex_lock 会发生什么?我怎样才能控制这些东西?这是我的代码:

#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;
}

抱歉发了这么长的帖子,但我是线程的新手,我愿意学习。您还知道有关 Linux 线程和网络的一些很好的引用资料或类(class)/教程吗?我想学习创建一个聊天客户端,我听说为此我必须了解线程和网络。问题是我不知道我学到的东西是否还好,因为我不知道我必须知道什么。

非常感谢:)

最佳答案

您的 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);

另外,没有必要仅仅为了使线程可连接而创建线程属性。当您为创建属性使用空指针时,这是默认情况。 POSIX 线程是可连接的,除非创建为分离的,或者使用 pthread_detach 转换为分离的。

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

关于c++ - POSIX C 线程。 pthread_cond_t 示例。没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10179546/

相关文章:

c++ - 从 Variant VT_ARRAY | 中读取和显示数据VT_BSTR?

C++ Python 将数据从 vector 转换为 ndarray

c++ - 关于使用 boost::variant 重新加载运算符的编译错误

php - 使用 php 变量和 SQL 语句的日期范围过滤器

java - System.getenv() 没有列出所有的环境变量

c 多线程

c++ - 并发链表

c++ - 如何启用 OpenMP w/OpenCV 应用程序?

node.js - 从 JavaScript (node.js) 在 shell 中设置变量

c++ - 仅在守护线程返回后删除它