Chinaunix首页 | 论坛 | 博客
  • 博客访问: 175814
  • 博文数量: 13
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 832
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-16 22:43
个人简介

最近关注Python,Linux,LLVM

文章分类

全部博文(13)

文章存档

2014年(13)

分类: C/C++

2014-05-12 10:57:49

前言

如果已经熟悉POSIX线程,那么C++11的线程也不会陌生,可以看做将POSIX线程API的子集做了高层抽象,一个好处就是更容易写跨平台线程应用,下文简要罗列C++11线程的几个重要组成部分,最后给一个简单的线程池实现。

Threads --- 线程创建与回收

线程构造函数,参数f可以是普通函数或类成员函数 
  1. template< class Function, class... Args >
  2. explicit thread( Function&& f, Args&&... args );
线程ID,全局唯一,线程退出后会可能被重用
  1. std::thread::id get_id() const;
阻塞当前运行线程,直到目标线程执行完毕
  1. void join();
Mutual exclusion --- 互斥锁

基本的0-1互斥锁,支持lock/unlock/try_lock 
  1. class mutex;
以RAII(Resource Acquisition Is Initialization)的方式使用mutex
  1. template< class Mutex >
  2. class lock_guard;
movable mutex,支持各种mutex场景
  1. template< class Mutex >
  2. class unique_lock;
Condition variables --- 条件变量

与std::unique_lock配合使用的条件变量,常用方法wait/notify_one/notify_all 
  1. class condition_variable;
Atomics --- 原子操作

C++唯一可以无锁(lock-free)异步访问的数据结构。这里是一个雷区,有很多晦涩和反直觉的现象,在100%理解相关概念之前,只用bool标志读写或计数器自增之类简单功能吧!

Futures --- 异步或并行执行的高层接口

是上面功能的高层抽象,让异步或并行用起来更简单,直接看参考手册即可。

Thread Pool Executor---  线程池示例

简单的线程池,但已经涉及到上文的多数功能

点击(此处)折叠或打开

  1. #include <algorithm>
  2. #include <atomic>
  3. #include <condition_variable>
  4. #include <functional>
  5. #include <mutex>
  6. #include <queue>
  7. #include <thread>
  8. #include <vector>

  9. #include <iostream>
  10. #include <chrono>

  11. namespace concurrent {

  12. namespace futures {

  13. class ThreadPoolExecutor {

  14.     typedef std::function<void()> Function;

  15. public:
  16.     ThreadPoolExecutor(int maxworkers): _exit_flag(false)
  17.     {
  18.         int num;
  19.         if (maxworkers > 0) {
  20.             num = maxworkers;
  21.         } else {
  22.             num = std::max(1, (int)std::thread::hardware_concurrency());
  23.         }
  24.         for ( ; num > 0; num--) {
  25.             _workers.emplace_back(&ThreadPoolExecutor::_run, this);
  26.         }
  27.     }
  28.     ~ThreadPoolExecutor()
  29.     {
  30.         if (!_exit_flag.load()) {
  31.             stop();
  32.         }
  33.     }

  34.     void submit(Function&& f)
  35.     {
  36.         {
  37.             std::lock_guard<std::mutex> lg(_cond_mutex);
  38.             _tasks.emplace(f);
  39.         }
  40.         _cond_var.notify_all();
  41.     }

  42.     void join()
  43.     {
  44.         for (auto &t: _workers) {
  45.             t.join();
  46.         }
  47.     }

  48.     void stop()
  49.     {
  50.         _exit_flag.store(true);
  51.         _cond_var.notify_all();
  52.         join();
  53.     }

  54. private:
  55.     void _run()
  56.     {
  57.         Function job;
  58.         auto wakeup = [&]{ return _exit_flag.load() || !_tasks.empty(); };
  59.         while (!_exit_flag.load()) {
  60.             {
  61.                 std::unique_lock<std::mutex> ul(_cond_mutex);
  62.                 _cond_var.wait(ul, wakeup);
  63.                 if (_exit_flag.load()) break;
  64.                 job = _tasks.front();
  65.                 _tasks.pop();
  66.             }
  67.             job();
  68.         }
  69.     }

  70. private:
  71.     std::vector<std::thread> _workers;
  72.     std::queue<Function> _tasks;
  73.     std::mutex _cond_mutex;
  74.     std::condition_variable _cond_var;
  75.     std::atomic<bool> _exit_flag;

  76. }; // class ThreadPoolExecutor

  77. }; // namespace futures

  78. }; // namespace concurrent

  79. void print(int num, char c)
  80. {
  81.     for (int i = 0; i < num; ++i) {
  82.         std::cerr << c << ' ';
  83.         std::this_thread::sleep_for(std::chrono::milliseconds(100));
  84.     }
  85. }

  86. using namespace concurrent::futures;

  87. int main(int argc, char* argv[])
  88. {
  89.     std::vector<char> sample{'a', 'b', 'c', 'd', 'e'};
  90.     ThreadPoolExecutor pool(0);

  91.     for (auto v: sample) {
  92.         pool.submit(std::bind(print, 100, v));
  93.     }
  94.     pool.join();

  95.     return 0;
  96. }







阅读(3711) | 评论(0) | 转发(1) |
0

上一篇:Python异步IO --- 轻松管理10k+并发连接

下一篇:没有了

给主人留下些什么吧!~~