热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在睡眠时唤醒std::thread

如何解决《如何在睡眠时唤醒std::thread》经验,为你挑选了4个好方法。

我正在使用C++ 11,我有一个std::thread类成员,它每2分钟向听众发送一次信息.其他它只是睡觉.所以,我让它睡了2分钟,然后发送所需的信息,然后再睡2分钟.

// MyClass.hpp
class MyClass {

    ~MyClass();
    RunMyThread();

private:
    std::thread my_thread;
    std::atomic m_running;
}


MyClass::RunMyThread() {

    my_thread = std::thread { [this, m_running] {
    m_running = true;
    while(m_running) {
        std::this_thread::sleep_for(std::chrono::minutes(2));
        SendStatusInfo(some_info);
    }
}};
}

// Destructor
~MyClass::MyClass() {
    m_running = false; // this wont work as the thread is sleeping. How to exit thread here?
}

问题:
这种方法的问题是我无法在线程休眠时退出线程.我从阅读中理解,我可以使用a唤醒它std::condition_variable并优雅地退出?但我正在努力寻找一个简单的例子,它可以满足上述场景中的要求.condition_variable我发现的所有例子看起来都太复杂了,我想在这里做些什么.

问题:
如何std::condition_variable在睡眠时使用a 唤醒线程并正常退出?或者,没有这种condition_variable技术,还有其他方法可以实现相同的目标吗?

另外,我看到我需要std::mutex结合使用std::condition_variable?这真的有必要吗?通过将std::condition_variable逻辑仅添加到代码中的所需位置,是否无法实现目标?

环境:
Linux和Unix与编译器gcc和clang.



1> Jonathan Wak..:

如何std::condition_variable唤醒线程并在睡眠时优雅地退出?或者没有condition_variable技术可以实现相同的其他方法吗?

不,不是在C++ 17的标准C++中(当然有非标准的,特定于平台的方法,并且可能会将某种信号量添加到C++ 2a中).

另外,我看到我需要std::mutex结合使用std::condition_variable?这真的有必要吗?

是.

通过将std::condition_variable逻辑仅添加到代码段中的所需位置,是否无法实现目标?

不可以.首先,您不能在condition_variable没有锁定互斥锁的情况下等待(并将锁定对象传递给等待函数),因此您无论如何都需要存在互斥锁.因为你必须有一个互斥体,要求服务员和通知者使用该互斥体并不是什么大问题.

条件变量受到"虚假唤醒"的影响,这意味着它们可以无缘无故地停止等待.为了告诉它是否因为被通知而醒来,或者虚假地醒来,你需要一些由通知线程设置并由等待线程读取的状态变量.因为该变量由多个线程共享,所以需要安全地访问它,这是互斥锁所确保的.

即使您使用原子变量作为共享变量,您仍然通常需要一个互斥锁来避免错过通知.

这些都在https://github.com/isocpp/CppCoreGuidelines/issues/554中有更详细的解释.


*"即使您使用原子变量作为共享变量,您仍然通常需要一个互斥锁以避免错过通知."*真正是使这成为最佳答案的原因.如果你有线程安全的情况,通常会认为你不需要互斥锁,这会导致可怕的头痛.编辑:似乎斯拉瓦的答案也提到了它.

2> Slava suppor..:

我如何使用std :: condition_variable来唤醒线程并在它休眠时正常退出?

你使用std::condition_variable::wait_for()而不是std::this_thread::sleep_for()和第一个可以被std::condition_variable::notify_one()或中断std::condition_variable::notify_all()

另外,我看到我需要将std :: mutex与std :: condition_variable一起使用?这真的有必要吗?通过将std :: condition_variable逻辑仅添加到代码段中的所需位置,是否无法实现目标?

是的,它必须使用std::mutexstd::condition_variable和你应该使用它,而不是让你的旗帜std::atomic为尽管标志本身你就必须竞争条件在你的代码,你会发现,有时候你的睡眠线程将错过通知,如果你不会在这里使用互斥体的原子.



3> Maxim Egorus..:

一个工作示例供您使用std::condition_variable:

struct MyClass {
    MyClass()
        : my_thread([this]() { this->thread(); })
    {}

    ~MyClass() {
        {
            std::lock_guard l(m_);
            stop_ = true;
        }
        c_.notify_one();
        my_thread.join();
    }

    void thread() {
        while(this->wait_for(std::chrono::minutes(2)))
            SendStatusInfo(some_info);
    }

    // Returns false if stop_ == true.
    template
    bool wait_for(Duration duration) {
        std::unique_lock l(m_);
        return !c_.wait_for(l, duration, [this]() { return stop_; });
    }

    std::condition_variable c_;
    std::mutex m_;
    bool stop_ = false;
    std::thread my_thread;
};



4> SergeyA..:

有一个令人遗憾但却确实如此的事实 - 你正在寻找的是一个信号,并且Posix线程没有真正的信令机制.

此外,与任何时序相关联的唯一Posix线程原语是条件变量,这就是您的在线搜索引导您的原因,并且由于C++线程模型大量构建在Posix API上,因此在标准C++中Posix兼容原语就是你的全部.得到.

除非你愿意去Posix之外(你没有指出平台,但是有本机平台方式来处理那些没有这些限制的事件,特别是eventfd在Linux中),你将不得不坚持条件变量,是的,使用条件变量需要互斥锁,因为它内置于API中.

您的问题没有明确要求代码示例,所以我没有提供任何代码示例.如果你想要一些,请告诉我.


推荐阅读
  • CentOS7.8下编译muduo库找不到Boost库报错的解决方法
    本文介绍了在CentOS7.8下编译muduo库时出现找不到Boost库报错的问题,并提供了解决方法。文章详细介绍了从Github上下载muduo和muduo-tutorial源代码的步骤,并指导如何编译muduo库。最后,作者提供了陈硕老师的Github链接和muduo库的简介。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 原文地址http://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/最开始时 ... [详细]
  • 【技术分享】一个 ELF 蠕虫分析
    【技术分享】一个 ELF 蠕虫分析 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 负载均衡_Nginx反向代理动静分离负载均衡及rewrite隐藏路径详解(Nginx Apache MySQL Redis)–第二部分
    nginx反向代理、动静分离、负载均衡及rewrite隐藏路径详解 ... [详细]
  • 第四讲ApacheLAMP服务器基本配置Apache的编译安装从Apache的官方网站下载源码包:http:httpd.apache.orgdownload.cgi今 ... [详细]
  • 三、查看Linux版本查看系统版本信息的命令:lsb_release-a[root@localhost~]#lsb_release-aLSBVersion::co ... [详细]
  • centos6.8 下nginx1.10 安装 ... [详细]
  • Linux下C语言的几道经典面试题小结(分享)
    本篇文章整理了几道Linux下C语言的经典面试题,相信对大家更好的理解Linux下的C语言会有很大的帮助,欢迎大家探讨指正。1、如果在Linux下使用GCC ... [详细]
author-avatar
秋静222
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有