博客
关于我
(C++11/14/17学习笔记):std::atomic续、std::async与std::thread对比
阅读量:342 次
发布时间:2019-03-04

本文共 3269 字,大约阅读时间需要 10 分钟。

std::atomic续谈与std::async与std::thread对比

原子操作std::atomic续谈

在多线程编程中,原子操作是保证在多个线程之间保持一致性和正确性的关键。C++中的std::atomic提供了一种轻量级的原子操作机制,适用于处理不可线性化的变量操作。以下是关于std::atomic的一些关键点:

  • 原子操作的支持操作

    std::atomic支持以下操作:++--+==|=^=。这些操作在多线程环境下保证原子性,防止数据竞争和舍去。例如,my_count += 1 会比 my_count = my_count + 1 更安全,因为前者不会在操作过程中被打断。

  • 原子操作的实现方式

    可以通过std::atomic<int>类来封装整数类型的变量,像操作普通变量一样使用。例如:

    #include 
    #include
    #include
    int my_count{ 0 }; // 使用std::atomic
    封装int变量void my_thread() { for (int i = 0; i < 1000000; ++i) { my_count += 1; // 原子操作,保证线程安全 }}int main() { std::thread threadObj1(my_thread); std::thread threadObj2(my_thread); threadObj1.join(); threadObj2.join(); std::cout << "两个线程执行完毕,最终 my_count的值是" << my_count << std::endl; return 0;}

    通过上述代码可以看到,多个线程同时对my_count进行操作时,结果仍然是正确的。

  • 注意事项

    如果使用my_count = my_count + 1,则不一定保证原子性,因为在某些情况下可能会导致不可见的读写冲突。因此,建议在多线程环境下始终使用支持的原子操作符。


std::async与std::thread的区别

std::async和std::thread都是用于在C++中创建和管理线程的工具,但它们在工作机制和使用方式上有显著的不同。以下是详细对比:

1. std::async的参数和作用

std::async接受一个入口函数作为参数,可以通过以下方式使用:

#include 
#include
#include
using namespace std;future
result = async(mythread);// 或者future
result = async(std::launch::async, mythread);
  • 参数说明

    • std::launch::deferred:延迟调用,异步任务不会立即执行。
    • std::launch::async:强制在新线程上执行异步任务。
    • 默认参数:std::launch::async | std::launch::deferred,系统会自行选择策略。
  • 作用

    std::async创建的是一个异步任务,而不是直接创建线程。任务的执行方式取决于系统的资源情况:

    • 如果资源充足,系统可能选择在新线程上执行。
    • 如果资源紧张,系统可能选择延迟执行任务。

2. std::thread的特点

  • 资源消耗:std::thread会直接创建新线程。如果系统资源紧张,可能会抛出异常,导致程序崩溃。
  • 线程管理:创建线程后,必须调用join()来等待线程完成,否则可能导致资源泄漏。
  • 返回值:线程函数返回值不易获取,通常需要通过共享变量的方式传递。

3. std::async的灵活性

  • 资源管理:如果系统资源紧张,std::async不会强制创建线程,而是将任务推迟到future的get()wait()方法调用时执行。
  • 线程调度:异步任务可以在等待future结果的线程上自动执行,这避免了不必要的线程切换开销。

4. 资源限制的影响

  • std::thread:线程数量过多可能导致系统资源耗尽,甚至崩溃。
  • std::async:如果系统资源紧张,异步任务可能不会立即创建线程,而是等待future的调用执行。这种方式在资源受限的情况下更可靠。

std::async的不确定性问题

在使用std::async时,可能会遇到不确定性问题。例如,系统可能选择使用std::launch::deferred(延迟调用)或std::launch::async(立即创建新线程)。要解决这种不确定性,可以通过以下方式判断任务执行情况:

示例代码

#include 
#include
#include
#include
using namespace std;int mythread() { cout << "mythread start" << "ThreadId = " << this_thread::get_id() << endl; cout << "mythread end" << "ThreadId = " << this_thread::get_id() << endl; return 100;}int main() { cout << "MainThreadID = " << this_thread::get_id() << endl; future
result = async(mythread); future_status status = result.wait_for(0s); // 等待0秒判断状态 if (status == future_status::deferred) { cout << result.get() << endl; } else if (status == future_status::ready) { cout << "线程成功执行完毕并返回!" << endl; cout << result.get() << endl; } else if (status == future_status::timeout) { cout << "超时线程没执行完!" << endl; cout << result.get() << endl; } return 0;}

通过result.wait_for(0s),可以判断异步任务的执行方式:

  • future_status::deferred:任务被延迟执行。
  • future_status::ready:任务已经完成。
  • future_status::timeout:任务未完成,但超时。

总结

std::async与std::thread在多线程编程中的应用场景有显著不同。std::async更注重灵活性和资源管理,适合在资源有限的情况下使用。通过合理配置launch策略和检查future状态,可以有效应对异步任务的不确定性问题。在实际开发中,应根据具体需求选择适合的线程创建方式,同时注意资源管理和状态判断,以确保程序的稳定性和性能。

转载地址:http://zdyr.baihongyu.com/

你可能感兴趣的文章
添加Selinux权限
查看>>
ifconfig网络配置信息解析
查看>>
Linux下解压命令
查看>>
(2019.9.10测试可用)如何在Windows的cmd中使用ls命令
查看>>
多因子策略中的IC、IR是什么,以及如何计算
查看>>
pd.resample('B')指重采样为工作日
查看>>
债券中的久期是什么意思
查看>>
MA、WMA、EMA、EXPMA区别及公式详述
查看>>
量化新手初识docker
查看>>
量化新手初识流数据表
查看>>
Linux中常见的echo是什么意思
查看>>
国内量化交易现状总结
查看>>
阿里云云解析DNS各种概念深度剖析
查看>>
《期权、期货及其他衍生产品》读书笔记(第五章:确定远期和期货价格)
查看>>
理解Linux下的各种发行版本:内核、Ubuntu、CentOS、LAMP、LNMP
查看>>
SQLite基础用法
查看>>
(20200328已解决)从docker容器内复制文件到宿主机
查看>>
理解Docker ulimit参数
查看>>
pandas.groupby().rank()用法详解
查看>>
Factor Exposure因子暴露
查看>>