zoukankan      html  css  js  c++  java
  • c++11并发机制

    传统意义上OS提供的并发机制包含进程和线程两个级别。考虑到实际复杂性,c++11仅提供了线程并发机制。
    c++11提供的线程并发机制主要位于四个头文件中:、<condition_variable>、
    线程并发机制包括线程管理、原子操作、线程同步对象。

    线程管理

    c++11中将可并发执行的运算成为一个任务(task),在OS的线程模型中,一个任务就是一个线程,实际需要在创建时指定线程函数。c++基于此提供了更为优雅的线程处理模型,不需要关心类型转换和指针的处理,所有线程管理的模型是基于std::thread实现的。在c++中一个任务通常是指函数、函数对象或Lamda表达式。比如下面代码:

    // thread util sample 1
    #include <iostream>
    #include <thread>
    using namespace std;
    
    void TaskFunc()
    {}
    
    class TaskObj
    {
    public:
    	TaskObj(){}
    	void operator()()
    	{}
    };
    
    int main(int argc, char ** argv)
    {	
    	thread t_func{TaskFunc};
    	thread t_obj{TaskObj()};
    	
    	t_func.join();
    	t_obj.join();
    	return 0;
    }
    

    创建thread对象时,就是线程启动的时候;thread::join()函数用于等待线程函数执行完成。

    线程启动时的参数传递

    上面代码(sample 1)中线程函数没有参数,如果需要给线程函数传递参数可以参考下面代码(参数类型可按值传递、按指针传递或按类型传递)。

    // thread util sample 2
    void TaskFunc(int i)
    {}
    
    class TaskObj
    {
    public:
    	TaskObj(int i):m_value(i){}
    	void operator()()
    	{m_value=123;}
    private:
    	int m_value{0};
    };
    
    int main(int argc, char ** argv)
    {	
    	int cur_value{100};
    	thread t_func{TaskFunc, cur_value};
    	thread t_obj{TaskObj{cur_value}};
    	
    	t_func.join();
    	t_obj.join();
    	return 0;
    }
    

    原子操作

    操作系统中轻量级的线程同步机制通常是原子操作,c++11提供了相应机制,所有文件位于中。主要包含std::atomic模板类和std::atomic_flag类。
    具体的建议参考atomic header。下面是一个说明int自增的原子函数

    // atomic::operator++ example
    #include <iostream>       // std::cout
    #include <atomic>         // std::atomic
    #include <thread>         // std::thread
    #include <vector>         // std::vector
    
    std::atomic<int> ready{0};
    
    void AtomicIncreasement (int id) 
    {
      ++ready;
    };
    
    int main(int argc, char** argv)
    {
      std::vector<std::thread> threads;
      std::cout << "spawning 5 threads that do incereasement...
    ";
      for (int i=1; i<=5; ++i) threads.push_back(std::thread(AtomicIncreasement,i));
      for (auto& th : threads) th.join();
      
      std::cout << ready << std::endl;
    
      return 0;
    }
    

    输出如下:

    spawning 5 threads that do incereasement...
    5

    线程同步对象

    c++11中提供了两种线程同步机制,mutex和condition_variable,分别对应Windows同步机制中的互斥量和事件。当然,c++中也对各个部分做了详细划分,以mutex为例,分为以下四种(位于头文件中):

    • mutex
    • recursive_mutex
    • timed_mutex
    • recursive_timed_mutex

    同时也提供了辅助的机制,比如unique_lock、lock_guard用于实现自动锁定和释放mutex。
    比如下面例子说明了mutex的调用逻辑:

    // mutex example
    #include <iostream>       // std::cout
    #include <thread>         // std::thread
    #include <mutex>          // std::mutex
    
    std::mutex mtx;           // mutex for critical section
    
    void print_block(int n, char c) 
    {
      // critical section (exclusive access to std::cout signaled by locking mtx):
      mtx.lock();
      for (int i=0; i<n; ++i) { std::cout << c; }
      std::cout << '
    ';
      mtx.unlock();
    }
    
    void print_block_auto(int n, char c) 
    {
      // critical section (exclusive access to std::cout signaled by locking mtx):
      std::unique_lock<std::mutex> lck{mtx};
      for (int i=0; i<n; ++i) { std::cout << c; }
      std::cout << '
    ';
    }
    
    int main ()
    {
      std::thread th1{print_block, 50, '*'};
      std::thread th2{print_block_auto, 50, '$'};
    
      th1.join();
      th2.join();
    
      return 0;
    }
    

    针对windows下的WaitForMultipleObject函数,c++提供了defer_lcok和lock(可变参数模块),用于实现同时等待多个同步对象。
    关于condition_variable的介绍,建议参考<condition_variable>

    线程返回参数处理

    传统的线程返回值,可以通过指针和引用处理,但如何实现类似windows下线程函数返回值的处理逻辑,c++也提供了这种机制,相关机制位于头文件中(http://www.cplusplus.com/reference/future/)。promise和packaged_task作为数据载体,future作为数据接收者。
    下面是两个说明future和promise、packaged_task的使用。

    // promise example
    #include <iostream>       // std::cout
    #include <functional>     // std::ref
    #include <thread>         // std::thread
    #include <future>         // std::promise, std::future
    
    void print_int (std::future<int>& fut) {
      int x = fut.get();
      std::cout << "value: " << x << '
    ';
    }
    
    int main ()
    {
      std::promise<int> prom;                      // create promise
    
      std::future<int> fut = prom.get_future();    // engagement with future
    
      std::thread th1 (print_int, std::ref(fut));  // send future to new thread
    
      prom.set_value (10);                         // fulfill promise
                                                   // (synchronizes with getting the future)
      th1.join();
      return 0;
    }
    
    // packaged_task example
    #include <iostream>     // std::cout
    #include <future>       // std::packaged_task, std::future
    #include <chrono>       // std::chrono::seconds
    #include <thread>       // std::thread, std::this_thread::sleep_for
    
    // count down taking a second for each value:
    int countdown (int from, int to) {
      for (int i=from; i!=to; --i) {
        std::cout << i << '
    ';
        std::this_thread::sleep_for(std::chrono::seconds(1));
      }
      std::cout << "Lift off!
    ";
      return from-to;
    }
    
    int main ()
    {
      std::packaged_task<int(int,int)> tsk (countdown);   // set up packaged_task
      std::future<int> ret = tsk.get_future();            // get future
    
      std::thread th (std::move(tsk),10,0);   // spawn thread to count down from 10 to 0
    
      // ...
    
      int value = ret.get();                  // wait for the task to finish and get result
    
      std::cout << "The countdown lasted for " << value << " seconds.
    ";
    
      th.join();
    
      return 0;
    }
    

    附加说明

    c++11也提供了其他机制比如thread_local线程局部变量的存储限定符、once_flag用于标识仅初始化一次的处理逻辑以及简化版的async()函数——支持局部语法的并行化。

    本文涉及的代码可以直接从我的git下载:https://git.oschina.net/Tocy/SampleCode.git ,位于c++11目录下,名字前缀为thread_util_sample*.cpp。

  • 相关阅读:
    DNS欺骗&嗅探监听
    linux下的ARP攻击(kali)
    隐匿攻击
    跨边界传输之反弹shell
    跨边界传输之内网代理
    跨边界传输之端口转发
    权限维持
    内网提权-服务篇
    内网提权-系统篇
    Laxcus大数据管理系统2.0(14)- 后记
  • 原文地址:https://www.cnblogs.com/tocy/p/cpp11_concurrency_utility.html
Copyright © 2011-2022 走看看