pthread_cond_signal 导致死锁

2024-01-25

我有一个程序,当其中一个线程调用时会死锁pthread_cond_siganl(或广播)。 该问题在主程序中可以 100% 重现。我无法弄清楚它出了什么问题,因此提取了调用 wait 和 signal 的代码段。然而,僵局cannot与提取的问题一起重现。

Running valgrind主程序上不会报告任何无效的读/写或内存泄漏。

我想知道调用时出现死锁的可能原因有哪些pthread_cond_signal.

提取的片段如下。

#include <pthread.h>
#include <math.h>
#include <syscall.h>
#include <assert.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

void Task() {
    cerr << syscall(SYS_gettid) << " In Task, sleeping..." << endl;
    sleep(5);
}

pthread_mutex_t lock;
pthread_cond_t cond;
bool doingTheTask= false;

void* func(void* ) { 
    pthread_mutex_lock(&lock);
    if (doingTheTask) {
        cerr << syscall(SYS_gettid) << " wait... " << endl;
        while ( doingTheTask) {//spurious wake-up
            cerr << syscall(SYS_gettid) << " waiting..." << endl ;
            pthread_cond_wait(&cond, &lock);
            cerr << syscall(SYS_gettid) << " woke up!!!" << endl ;
        }
    }
    else {
        cerr << syscall(SYS_gettid) << " My Turn to do the task..." << endl;
        assert( ! doingTheTask );
        doingTheTask= true;
        pthread_mutex_unlock(&lock);
        Task();
        cerr << syscall(SYS_gettid) << " Before trying to acquire lock" << endl;
        pthread_mutex_lock(&lock);
        cerr << syscall(SYS_gettid) << " After acquiring lock" << endl ;
        assert( doingTheTask );
        doingTheTask = false;
        cerr << syscall(SYS_gettid) << " Before broadcast" << endl;
        pthread_cond_broadcast(&cond);
        cerr << syscall(SYS_gettid) << " After broadcast" << endl;
    }
    pthread_mutex_unlock(&lock);
    return NULL;
}


int main() {
    pthread_mutex_init(&lock,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_t thread[2];

    for ( int i = 0 ;  i < 2 ; i ++ ) {
        if (0 != pthread_create(&thread[i], NULL, func, NULL) ) {
            cerr << syscall(SYS_gettid) << " Error creating thread" << endl;
            exit(1);
        }
    } 

    for ( int i = 0 ;  i < 2 ; i ++ ) {
        pthread_join(thread[i],NULL);
    }
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);

    return 0;
}

唯一重要的部分是 func 函数。其他部分只是为了编译而呈现。

正如我所说的问题在此程序中无法重现。 该代码片段与主程序的区别在于:

  • 在主程序中,mutex and condvar是成员字段,函数是成员方法。
  • 该任务执行一些任务而不是睡觉。
  • 多个线程可能会等待,我们应该广播而不是发出信号。然而,即使我使用信号和一个等待线程,死锁也是 100% 可重现的。

我试图用这段代码解决的问题是一种机制,当至少一个线程需要完成该任务时,该机制会执行一次该任务。但是任何两个线程都不应该并行执行该任务,一旦其中一个线程执行了该任务,其他线程就不需要执行该任务。此方法的客户端假设它会阻塞直到任务完成(因此我在看到有人正在执行任务后无法立即返回)。

死锁线程的回溯是:

#0  __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136
#1  0x00007ffff73e291c in pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:259

and

#0  __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136
#1  0x00007ffff73e30b1 in pthread_cond_signal@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S:142

pthread_cond_signal 死锁 https://stackoverflow.com/questions/4345315/pthread-cond-signal-deadlocks是一个类似的问题。但似乎提出问题的人有记忆损坏。我没有内存损坏(说valgrind).

该问题在我测试的两台机器上 100% 可重现。 (ArchLinux 最新版和 Uubntu 10.04.3)。

主程序的示例输出如下。它再次表明线程在调用之前阻塞pthread_cond_wait and pthread_cond_signal。 (第一列显示线程 ID)。

3967    In Task, sleeping...
3967    My Turn to do the task...
3967    In Task, sleeping...
3973    wait...
3973    waiting...
3976    <output from some other thread>
3967    Before trying to acquire lock
3967    After acquiring lock
3967    Before broadcast

主程序是用C++编写的。但我使用的是该语言的 C 部分,因此避免使用 C++ 标签。


愚蠢的错误。 我正在摧毁mutex and condvar在执行信号之前并等待。 要重现,只需在主函数中加入线程之前移动销毁函数即可。

令人惊讶的是,在我的两台机器上,这会产生 100% 一致(且错误)的行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pthread_cond_signal 导致死锁 的相关文章

随机推荐

  • 如何仅在 bash 中存在脚本时才执行该脚本?

    我想知道是否有一种更简单的方法可以仅在该脚本存在时才在 bash 中执行该脚本 我想要的相当于 if x name then name fi or x name name 我正在寻找的是类似的东西 exec if exist name 这消
  • Python-如何使用 re 来匹配整个字符串[重复]

    这个问题在这里已经有答案了 我正在验证用户输入的文本 以便它只接受字母而不接受数字 到目前为止 当我输入数字 例如 56 时 我的代码工作正常 它警告我应该只输入字母 而当我输入字母时 它不会返回任何内容 就像它应该做的那样 我的问题是 当
  • 使用YouTube Data API时如何避免视频信息获取的遗漏?

    假设 我想要实现的目标 我想使用YouTube Data API V3来无遗漏地获取视频ID 并找出问题的原因是在代码中还是在YouTube API端 的视频设置中 Problem 以下代码用于从YouTube Data API获取视频信息
  • “尝试向 Flutter 发送平台消息,但 FlutterJNI 与原生 C++ 分离。”启动后台服务并关闭应用程序后

    我正在尝试构建一个使用某些包作为位置的应用程序 https pub dev packages location https pub dev packages location 和指南针 https pub dev packages flut
  • 为什么采用一种定义规则,而不是一种声明规则?

    我已阅读以下材料 https www wikiwand com en One Definition Rule https www wikiwand com en One Definition Rule http en cppreferenc
  • 如何自动启用网络位置提供程序

    我正在通过网络获取纬度和经度 它给了我纬度和经度 但是如果我的NETWORK LOCATION PROVIDER未选中 它永远不会向我提供当前位置的纬度和经度 我想要的是 我怎样才能启用NETWORK LOCATION PROVIDER在不
  • Hibernate Spatial - “遇到无效的字节序标志值”异常

    我正在尝试在 PostgreSQL 9 3 上的 Hibernate Spatial 4 0 中运行一个简单的查询 我的表中有许多带有纬度 经度值的对象 并且我正在尝试查询位于特定纬度 经度的给定半径内的对象 几何值似乎没有任何问题地被持久
  • 如何在pygame中检测两个矩形物体或图像之间的碰撞

    我正在制作一款游戏 玩家必须使用碗来接住掉落的物品 我有一些列表中的项目图像和一个用于接住项目的碗的图像 物品会继续下落 如果到达边界 下边缘 就会重置到屏幕顶部 我完成了这个逻辑 允许物品掉落 但我不知道如何检测碗和物品之间何时发生碰撞
  • 在 PyAudio 模块中安装时出现错误

    经过无数次尝试后 我仍然无法安装 PyAudio 而不会出现此错误 我尝试过使用许多方法 包括 pipwin 但它没有被识别为真正的函数 如何安装 PyAudio ERROR Command errored out with exit st
  • 检查提交消息中的特定字符串 - SVN Precommit Hook

    我期望 svn 提交消息中出现以下格式 描述 更改的一些描述 实体 变更请求编号 如果提交时的注释不遵循上述格式 则应抛出错误消息 这个想法是检查提交消息中的关键字符串 Description 和 Entity 我还在检查消息中是否存在评论
  • 为每个页面添加固定的页眉/页脚 jsPDF

    我在用jsPDF https github com MrRio jsPDF从我的网络应用程序的动态 HTML 内容生成 PDF 现在我正在尝试为这些 PDF 提供独特的布局 我想为 PDF 的每一页添加 页眉 和 页脚 jsPDF 会自动生
  • 为面向文档的数据库设计记录键 - 最佳实践

    我们的团队已经开始开发由 Couchbase DB 支持的应用程序 对于我们每个人来说 这都是第一次使用非 SQL 数据库 我们已经开始定义我们的实体 并采用 Couchbase 手册建议的使用 类型 前缀的做法 Entity A key
  • iOS - RestKit 并清除所有数据?

    我使用 RestKit 进行 Web 服务调用 缓存和 etag 我实现了自己的 coredata 模型和 ManagedObjects 用户退出后 我需要清除数据库中的所有数据 我能够成功删除 sqlite 文件并重新创建它 但我找不到清
  • SQLite查询进度条

    我在用sqlite来自 C 我想实现一个进度条 通知用户搜索的进度 Using sqlite3 progress handler http www sqlite org sessions c3ref progress handler htm
  • 实时音频流容器格式

    当我开始接收实时音频 无线电 流 例如 MP3 或 AAC 时 我认为接收到的数据不是原始比特流 即原始编码器输出 但它们总是被包装成某种容器格式 如果这个假设是正确的 那么我想我无法从流的任意位置开始流式传输 但我必须等待某个同步字节 是
  • 我可以在64位python中使用32位dll或exe吗?

    当我使用CDLL在32位python中调用32位dll时 它运行良好 但不幸的是 在我的64位win7操作系统中只安装了64位python 当调用它时 它不是一个有效的win32应用程序 我可以在64位python中使用32位dll或exe
  • 将一行从一个列表视图发送到另一个列表视图

    我在同一个活动中有两个列表视图 其中一个有元素 另一个是空的 我想通过长按将任何元素发送到第二个 lisview 我希望元素执行与第一个列表视图中相同的操作 打开一项活动 这是我的代码 请告诉我该怎么做 MainActivity java
  • LaravelWhere 和 OrWhere 多个条件

    我有以下查询 items UserItems join items items id user items item id gt where user id this gt id gt where quantity gt 0 gt wher
  • 跨多个 Docker 镜像的 Jenkins 管道

    使用 Jenkins 中的声明性管道 如何跨 Docker 映像的多个版本运行阶段 我想在 python 2 7 3 5 和 3 6 上执行以下 jenkinsfile 下面是用于在 docker 容器中构建和测试 python 项目的管道
  • pthread_cond_signal 导致死锁

    我有一个程序 当其中一个线程调用时会死锁pthread cond siganl 或广播 该问题在主程序中可以 100 重现 我无法弄清楚它出了什么问题 因此提取了调用 wait 和 signal 的代码段 然而 僵局cannot与提取的问题