读书笔记《C++并发编程实战》(4) - 同步并发操作

等待事件:
    条件变量等待:
        std::condition_variable/std::condition_variable_any,前者配合std::mutex以及std::unique_lock、std::lock_guard,
    后者可配合类似互斥体(包括互斥体)的类型工作,不过因其内部持有std::mutex对象成员的锁保护,性能和大小上会有一定的代价。
    条件变量使用wait等待条件成立以便继续执行,notify_one通知任意某个正在执行wait的等待线程可继续执行,notify_all通知所有的等待
    线程可继续执行。
    
    future等待:
        一种一次性事件;也即当该等待future变为就绪状态,则不可复位其状态。
    提供两种future,一种唯一future(std::future)、另一种共享future(std::shared_future),前者的实例指向一个事件,后者的多个共享
    实例可关联同一事件。对于后者当事件就绪时,所有实例均变为就绪状态。
    
    异步获取后台计算结果:
        std::async启动一个异步任务,其返回一个std::future对象,该对象将持有函数的返回值;此时调用
    该对象的get接口(线程将被阻塞直到该future对象就绪并获取返回值)。std::future模板参数即为获取类型返回的值。
    std::async重载版本支持指定启动方式,std::launch::deferred/std::launch::async,前者为延迟直到调用wait/get时运行,后者立即开启
    新的线程运行,若为组合,则根据平台具体实现来选择。
    std::async可以启动一个异步任务,此外std::packaged_task<>、std::promise<>也可以实现启动并行运行的任务。
    std::async是更高层次上的异步操作,使我们不用关注线程创建内部细节,能方便的获取异步执行状态和结果。
    
        std::packaged_task<>将一个future绑定到一个函数或是可调用对象上,模板参数为该函数签名。std::packaged_task重载了operator();
    即可调用执行任务,此后在其他地方调用该对象的get_future接口,即可获取到关联的std::future对象;相对std::promise<>,前者保存的
    是一个可调用函数或对象(以实现异步操作),后者是一个共享状态值;共同点是均通过get_future获取到关联的future对象,以获取最后的
    调用函数或对象的返回值或者设置的值。
        
        std::promise<>一个异步服务提供者,通过设置值得方式,使得与之关联的std::future对象来读取设置值。promise中set_value接口
    或者设置异常时set_exception可使得std::future变为就绪状态。同样的std::promise接口get_future获取到关联的future对象。
    std::future可保持值或者异常。这样在不同地方设置promise值,另一个地方通过future对象获取该设置值。
    
    共享std::shared_future:
        std::shared_future可有多个实例引用同一个事件的相关状态,具有可复制性,std::future具有可移动性,也即移动后其valid将返回无效。
    而被赋值移动的future对象变得有效,此外std::shared_future可多次调用get获取共享状态。std::future可转为std::shared_future对象,被
    转移后std::future也会变得无效。
    
基于时间限制的等待:
    chrono:时间库,主要提供了时间概念相关的模板类或者工具。主要有:时间段duration、时间点time_point、时钟clock;
    时钟clock:system_clock(系统时钟(不匀速,可变))、steady_clock(稳定/均速时钟、不可变)、high_resolution_clock(高精度时钟,
    可能为均速时钟或系统时钟)。
    时间段duration:duration<type T, std::ratio<N,M>>,模板参数T为存储时间类型,参数ration则为分数表示每个时间段单位表示多少秒,其中
    N/M的值表示多少秒为一个时间段,如<3600,1>表示3600秒也即1小时为一个时间段,<1,1000>表示0.001秒即1毫秒为一个时间段,标准库已提供
    一些常用的预定义时间段如std::chrono::milliseconds、std::chrono::hours等。
    工具转换函数std::chrono::duration_cast<>可实现时间段之间的显式转换。
    时间点time_point:std::chrono::time_point。
    
    C++中接受超时相关的函数主要有:
        std::this_thread::sleep_for,std::this_thread::sleep_until;
        std::condition_variable::wait_for,std::condition_variable::wait_until;
        std::condition_variable_any::wait_for,std::condition_variable_any::wait_until;
        std::timed_mutex::try_lock_for,std::timed_mutex::try_lock_until;
        std::unique_lock::unique_lock,std::unique_lock::try_lock_for,std::unique_lock::try_lock_until;
        std::future::wait_for,std::future::wait_until;
        std::shared_future::wait_for,std::shared_future::wait_until;

避免共享可变数据的一些方法:
    采用函数式编程(FP)、通信顺序处理(CSP/MPI消息传递接口);
        
一些操作同步简化代码:
    带有future的函数式编程:借助std::future、std::async或者packaged_task与std::thread可实现并发操作。
    具有消息传递的同步操作:采用多线程实现不同任务的划分执行,线程间不再共享数据,线程间的通信通过共享的消息队列实现,
    以此多线程来划分关注点,简化设计和实现并发系统任务。

 

posted @ 2019-10-10 13:22  浩月星空  阅读(260)  评论(0编辑  收藏  举报