C++:Linux平台上的线程同步场景

2024-05-26

我正在为 Linux 平台实现多线程 C++ 程序,其中我需要类似于 WaitForMultipleObjects() 的功能。

在搜索解决方案时,我发现有一些文章描述了如何在 Linux 中实现 WaitForMultipleObjects() 功能,并附有示例,但这些示例不满足我必须支持的场景。

我的情况非常简单。我有一个守护进程,其中主线程向外界公开方法/回调,例如向 DLL 公开。 DLL 的代码不在我的控制之下。同一个主线程创建一个新线程“Thread 1”。线程 1 必须执行一种无限循环,其中它将等待关闭事件(守护程序关闭),或者等待通过上述公开的方法/回调发出信号的数据可用事件。

简而言之,线程将等待关闭事件和数据可用事件,其中如果发出关闭事件信号,则等待将满足并且循环将被打破,或者如果发出数据可用事件信号,则等待也将满足并且线程将进行业务处理。

在 Windows 中,它看起来非常简单。下面是针对我的场景的基于 MS Windows 的伪代码。

//**Main thread**

//Load the DLL
LoadLibrary("some DLL")

//Create a new thread
hThread1 = __beginthreadex(..., &ThreadProc, ...)

//callback in main thread (mentioned in above description) which would be called by the     DLL
void Callbackfunc(data)
{
    qdata.push(data);
    SetEvent(s_hDataAvailableEvent);
}

void OnShutdown()
{
    SetEvent(g_hShutdownEvent);
    WaitforSingleObject(hThread1,..., INFINITE);
    //Cleanup here
}

//**Thread 1**

unsigned int WINAPI ThreadProc(void *pObject)
{
    while (true)
    {

        HANDLE hEvents[2];
        hEvents[0] = g_hShutdownEvent;
        hEvents[1] = s_hDataAvailableEvent;

        //3rd parameter is set to FALSE that means the wait should satisfy if state of  any one of the objects is signaled.
        dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
        switch (dwEvent) 
        {   
            case WAIT_OBJECT_0 + 0: 
            // Shutdown event is set, break the loop
            return 0;   

            case WAIT_OBJECT_0 + 1:
            //do business processing here
            break; 

            default: 
            // error handling
        }
    }
}

我想在 Linux 上实现同样的功能。根据我的理解,当涉及到Linux时,它有完全不同的机制,我们需要注册信号。如果终止信号到达,进程就会知道它即将关闭,但在此之前,进程必须等待正在运行的线程正常关闭。


在 Linux 中执行此操作的正确方法是使用条件变量。虽然这与WaitForMultipleObjects在 Windows 中,您将获得相同的功能。

Use two bool确定是否有可用数据或必须关闭。 然后让关闭函数和数据函数都相应地设置布尔值,并向条件变量发出信号。

#include <pthread.h>

pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_t hThread1; // this isn't a good name for it in linux, you'd be 
                    // better with something line "tid1" but for 
                    // comparison's sake, I've kept this

bool shutdown_signalled;
bool data_available;

void OnShutdown()
{
    //...shutdown behavior...
    pthread_mutex_lock(&mutex);
    shutdown_signalled = true;
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cv);
}

void Callbackfunc(...)
{
    // ... whatever needs to be done ...
    pthread_mutex_lock(&mutex);
    data_available = true;
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cv);
}


void *ThreadProc(void *args)
{
    while(true){
        pthread_mutex_lock(&mutex);
        while (!(shutdown_signalled || data_available)){
            // wait as long as there is no data available and a shutdown
            // has not beeen signalled
            pthread_cond_wait(&cv, &mutex);
        }
        if (data_available){
            //process data
            data_available = false;
        }
        if (shutdown_signalled){
            //do the shutdown
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
        pthread_mutex_unlock(&mutex); //you might be able to put the unlock
        // before the ifs, idk the particulars of your code
    }
}
int main(void)
{
    shutdown_signalled = false;
    data_available = false;
    pthread_create(&hThread1, &ThreadProc, ...);
    pthread_join(hThread1, NULL);
    //...
}

我知道 Windows 也有条件变量,所以这看起来应该不会太陌生。我不知道 Windows 对它们有什么规则,但在 POSIX 平台上wait需要在 a 的内部while循环,因为可能会发生“虚假唤醒”。

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

C++:Linux平台上的线程同步场景 的相关文章

  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了
  • IO 密集型任务中的 Python 多线程

    建议仅在 IO 密集型任务中使用 Python 多线程 因为 Python 有一个全局解释器锁 GIL 只允许一个线程持有 Python 解释器的控制权 然而 多线程对于 IO 密集型操作有意义吗 https stackoverflow c
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 核心数据 iCloud 同步中的关系完整性和验证

    考虑以下简单的实体模型 实体 A 与实体 B 具有一对一关系 称为b 实体 B 具有逆对一关系 称为a 这两种关系都不是可选的 A B b lt gt a 假设我们有两个设备 1 和 2 开始完全同步 每个对象都有一个 A 类对象和一个 B
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 重载<<的返回值

    include
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 如何从应用程序扩展启动父 iOS 应用程序

    有谁知道如何从应用程序扩展的视图控制器启动父应用程序 我只想从其应用程序扩展启动主应用程序 在 WWDC 会议上为 iOS 和 OS X 创建扩展 第 1 部分 https developer apple com videos wwdc 2
  • 生成脚本 - 仅数据 - 循环依赖项发现错误

    我正在尝试生成数据库中所有数据的脚本 以便我可以将数据移动到另一台服务器上的相同数据库 在 SQL Server 2012 中 我右键单击源数据库 任务 gt 生成脚本 gt 为整个数据库和所有数据库对象编写脚本 gt 高级 gt 要编写脚
  • Bot 在本地计算机上的 Bot Framework Emulator 中运行,但在部署到 Microsoft Azure 后无法运行 - HTTP 状态代码 NotFound

    现在 我正在测试启动机器人项目所需的步骤2019 年虚拟演播室社区 测试机器人机器人框架模拟器 V4 然后将该机器人部署到 Microsoft Azure 现在 我正在测试 Virtual Studio Community 2019 中提供
  • 实时/热重载不适用于 dockerized NestJS API

    我遇到了一个奇怪的问题 我目前正在使用 Windows 10 并通过 WSL2 运行 docker 我在 Windows 文件管理器中克隆了存储库 并且我尝试在 DEV 中运行它 也就是说 一旦我更新了在我的本地存储库中的文件中 此更改反映
  • 检查 Firebase 中是否存在用户名[重复]

    这个问题在这里已经有答案了 我有一个这样的数据库 users UID1 用户名 用户 1 UID2 Username of user 2 UID3 Username of user 3 UID4 Username of user 4 等等
  • 如何在 *ngFor 中停止属性绑定到 Angular 中的每个元素

    在我的 html 中 我想将属性绑定应用于每个元素 我有一个点击和悬停事件 每当用户 将鼠标悬停或单击单个元素 但现在悬停或 单击发生在其中的每个元素上 ngFor 我想要它只 发生在他们选择 悬停的元素上 我需要什么 改变 我看到了另一个
  • 使用 jQuery 从字符中获取文本

    我想在出现特定字符后从字符串中获取文本 比方说 文本文本文本 abc 我想得到 abc jquery 中这是如何完成的 这对某些人来说可能是微不足道的 但我对 jQuery 没有什么经验 你可以这样做 var text texttextte
  • 有没有用于iPhone开发的高级手势库?

    iPhone 平台有许多常见的手势习惯用法 例如 有轻击 捏合和滑动等操作 每种操作都需要不同数量的手指 但是 当您开发应用程序时 您需要根据有关触摸次数和位置的低级信息来实现这些内容 看起来这是图书馆的主要候选者 您将注册一个委托 设置一
  • Excel的解析路径

    其实我想问以下问题 对于位于 目录中定义的 PATH 怎么能 我找出这些目录中的哪个 找到了 因为我需要使用 Process Run 从 C 运行 Excel 并且只需指示 Excel 即可正常工作 Windows 似乎知道在哪里可以找到它
  • 如何获取sql server 2005中数据库连接的详细列表?

    如何获取sql server 2005中数据库连接的详细列表 使用系统存储过程sp who2
  • Vue SPA - 如何在浏览器中呈现时隐藏 .vue 文件

    我正在开发一个用 Vue js 开发的单页应用程序 托管在 Node js 服务器上 目前它仍在开发中 但最终将暴露给外部客户 并且由于我们将处理敏感数据 我们希望避免在用户检查元素时看到 vue 文件和相对文件树结构在开发工具中 See
  • Magento 路由器 URL - 需要连字符的路径名称

    假设我使用自定义控制器 其 url 路径 前端名称为 customcategory 好吧 显然如果我有一个名为 TestController php 和indexAction的控制器文件 url 路径将是 customcategory te
  • 在tinymce 4中裁剪后上传图像

    我正在开发tinymce 并且已经实现了imagetools 现在 当图像插入到文本编辑器中 然后我编辑 裁剪图像时 它将图像 src 更改为类似的内容blob www localhost asdf ghij 我想要的是裁剪后我可以将此 u
  • PHP crypt() Blowfish 函数不工作

    这是我第一次在 PHP 中使用 crypt 函数 我不明白为什么它不起作用 我的代码基于这篇文章 http www techrepublic com blog australia secure passwords with blowfish
  • 跨数据库管理系统检查字符串是否为数字的方法

    好的 我有这个字段 code varchar 255 它包含我们导出例程中使用的一些值 例如 DB84 DB34 3567 3568 我需要仅选择自动生成的 全数字 字段 WHERE is numeric table code is num
  • 如何使用 ui-router 获取带有参数的先前状态

    问题陈述 我有一个 添加评论 按钮 只有当我登录系统时我才应该能够添加评论 但问题是我登录后无法返回 添加评论 页面 因为我不知道之前的状态或无法获取之前的状态 有没有更清洁的解决方案 我应该将登录页面设置为模态页面而不是新页面吗 我已经看
  • 在单个 C# 泛型方法中返回可为 null 和 null?

    C 泛型方法是否可以返回对象类型或 Nullable 类型 例如 如果我有一个安全的索引访问器List我想返回一个值 稍后我可以使用以下任一方法检查该值 null or HasValue 目前我有以下两种方法 static T SafeGe
  • 指针的 Fortran 副本

    我有一个包含指针 p 的 var 类型 我需要将 var 复制到与 var 类型相同的另一个变量 var1 上 通过执行 var1 var 在引号中 因为我不知道这是否是正确的方法 请参见下文 在我的实现中 var 和 var1 被传递给一
  • 是否可以在水晶报表中显示文本文件的内容

    我有一个水晶报告 其中包含绝对引用的文本文件的列表 每个正文行引用一个文本文件 e g line1 c file1 txt line2 c file2 txt 有什么办法可以在Crystal中显示这些文件的内容吗 即我希望每个水晶体线显示引
  • C++:Linux平台上的线程同步场景

    我正在为 Linux 平台实现多线程 C 程序 其中我需要类似于 WaitForMultipleObjects 的功能 在搜索解决方案时 我发现有一些文章描述了如何在 Linux 中实现 WaitForMultipleObjects 功能