C++并发与多线程 11_std::atomic叙谈std::launch(std::async) 深入

Posted TianSong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++并发与多线程 11_std::atomic叙谈std::launch(std::async) 深入相关的知识,希望对你有一定的参考价值。

std::atomic 叙谈

  • 原子类模板完全专用于基本整数类型(bool除外),以及 <cstdint> 中 typedef 所需的任何扩展整数类型。

专用的基本数据类型:

char
signed char
unsigned char
short
unsigned short
int
unsigned int
long
unsigned long
long long
unsigned long long
char16_t
char32_t
wchar_t
extended integral types (if any)

附加的成员函数:

atomic::fetch_add
atomic::fetch_sub
atomic::fetch_and
atomic::fetch_or
atomic::fetch_xor
atomic::operator++
atomic::operator--
operator (comp. assign.)
  • 对于 bool 实例化,仅支持常规原子操作。请注意,大多数 c-style 原子类型都是这些专门化的别名(或这些专门化继承的基类的别名)
  • 原子操作还部分专用于指针类型,具有以下附加成员函数:
atomic::fetch_add
atomic::fetch_sub
atomic::operator++
atomic::operator--
operator (comp. assign.)
  • atomic::store : 修改包含的值
  • atomic::load : 读取包含的值
// atomic::load/store example
#include <iostream>       // std::cout
#include <atomic>         // std::atomic, std::memory_order_relaxed
#include <thread>         // std::thread

std::atomic<int> foo (0);

// std::atomic<int> foo1(foo);          // error
// std::atomic<int> foo1(foo.load());   // ok

void set_foo(int x) {
  foo.store(x,std::memory_order_relaxed);     // set value atomically
  // 等价于 foo = x;
}

void print_foo() {
  int x;
  do {
    x = foo.load(std::memory_order_relaxed);  // get value atomically
  } while (x==0);
  std::cout << "foo: " << x << \'\\n\';
}

int main ()
{
  std::thread first (print_foo);
  std::thread second (set_foo,10);
  first.join();
  second.join();
  return 0;
}

输出:

foo: 10

std::launch(std::async) 深入理解

std::async

enum class launch : /* unspecified */ {
    async =    /* unspecified */,
    deferred = /* unspecified */,
    /* implementation-defined */
};
  • 此枚举类型用于定义 aync 异步调用中的启动策略。

launch::async

  • 入口函数由新线程异步调用,并将其返回其与共享状态的访问点同步。
#include <iostream>
#include <future>
#include <thread>

using namespace std;

bool async_func () {

    cout << "async_func begin " << std::this_thread::get_id() << endl;

    cout << "async_func end" << endl;

    return true;
}

int main ()
{
  cout << "main begin " << std::this_thread::get_id() << endl;

  std::future<bool> fut = std::async (launch::async, async_func);   // 创建新线程并调用线程入口函数

  cout << fut.get() << endl;

  cout << "main end" << endl;

  return 0;
}

输出:

main begin 1
async_func begin 2
async_func end
1
main end

launch::deferred

  • 入口函数延迟调用。
  • 在调用线程访问 future 对象的 wait, get 函数时,入口函数才被调用。
  • 同时未创建新线程,入口函数在 future 对象被调用的线程中执行。
#include <iostream>
#include <future>
#include <thread>

using namespace std;

bool async_func () {

    cout << "async_func begin " << std::this_thread::get_id() << endl;

    cout << "async_func end" << endl;

    return true;
}

int main ()
{
  cout << "main begin " << std::this_thread::get_id() << endl;

  std::future<bool> fut = std::async (launch::deferred, async_func);

  if (fut.wait_for(std::chrono::microseconds(0)) == std::future_status::deferred)   // 检查是否是 launch::deferred 
  {
    cout << "std::future_status::deferred" << endl;
  }

  cout << fut.get() << endl;    // 入口函数被调用

  cout << "main end" << endl;

  return 0;
}

输出:[注意两处打印的线程id]

main begin 1
std::future_status::deferred
async_func begin 1
async_func end
1
main end

launch::async | launch::deferred

  • 依据系统和库的实现,自动选择启动策略。
  • 准则主要为是否有足够的系统资源创建线程。
  • 这也是未明确指定参数时的默认实现。
std::future<bool> fut = std::async (launch::async|launch::deferred, async_func);

==

std::future<bool> fut = std::async (async_func);

以上是关于C++并发与多线程 11_std::atomic叙谈std::launch(std::async) 深入的主要内容,如果未能解决你的问题,请参考以下文章

C++并发与多线程 13_线程池浅谈,线程数量总结

C++并发与多线程 4_创建多个线程数据共享问题分析

C++并发与多线程 10_shared_futureautomic

C++并发与多线程 9_asyncfuturepackaged_taskpromise

C++并发与多线程 3_线程传参数详解,detach 注意事项

C++并发与多线程 2_线程启动结束,创建线程多种方法,join,detach