天天看点

C++ 多线程笔记小结

关于unique_lock和lock_guard的区别

unique_lock 和 lock_guard的区别:unique_lock只允许单独获取互斥器的所有权,其区别类似于unique_ptr和shared_ptr的区别。

关于future

future myFuture = async(task, 10);

//这里的async自动创建一个线程执行task函数,并将结果保存到myFuture中,这里future的模板参数要和函数task的返回类型一样。

int x = myFuture.get();

//获得task的执行结果并保存到x中。若task没有执行完就调用get(),那么主线程会阻塞直到task完成。

packaged_task< int(int) > myPackaged(task);

//首先创建packaged_task对象myPackaged其内部创建一个函数task和一个共享状态(用于返回task的结果)。

future myFuture = myPackaged.get_future;

//获取future对象用以返回task的任务结果。

Thread myThread(move(myPackaged),”hello world”);

//move 语义:packaged_task禁止copy constructer,因此用move 强制将左值转右值。

#include <iostream>      
#include <functional>     
#include <thread>         
#include <future>         
void print_int (std::future<int>& fut) {  
  int x = fut.get();
    //当promise::set_value()设置了promise的共享状态值后,fut将会通过future::get()获得该共享状态值,若promise没有设置该值那么fut.get()将会阻塞线程直到共享状态值被promise设置  
  std::cout << "value: " << x << '\n';
}  
int main ()  
{  
  std::promise<int> prom;           //创建一个promise对象  
  std::future<int> fut = prom.get_future();    
    //获取promise内部的future,fut将和promise共享promise中的共享状态,该共享状态用于返回计算结果  
  std::thread th1 (print_int, std::ref(fut));  //创建一个线程,并通过引用方式将fut传到print_int中  
  prom.set_value ();             //设置共享状态值 
  th1.join();            //等待子线程  
  return ;  
}  
           
将主线程即需要task结果的线程称为provider,称执行任务task或上面print_int的线程为executor(这里只是为了后面表述方便,没有科学考证的)。从上面的例子可以看出,简单的同步机制都是通过设置某种共享状态然后通过future获取该共享状态达到同步。 

packaged_task是一个对象其内部持有callable object,provider创建一个下线程executor执行任务,最后provider通过相关的future获取任务计算结果。和async差不多。只有任务结果的存取,没有其它交互。

promise是provider持有,executor持有相关的future,然后provider通过promise设定共享状态的值,future获取该共享值后执行某些任务。形式上和前面两个有点相反。