C++

C++并发编程实践

同步并发操作

Posted by w@hidva.com on February 3, 2016

等待未来事件

现实世界中的需求

  • 未来事件;(这是我瞎诌的一个概念),在未来某个时间点发生;并且只会发生一次;而且发生时可能会携带数据, 也可能不会.
  • 在编程中经常会碰到,一个线程需要等待未来事件发生后才能继续执行;或者多个线程等待同一个未来事件发生.

C++ future,shared_future 设施

  • future<T>,shared_future<T>的区别;就类似unique_ptr,shared_ptr之间的区别;即future<T> 对象是仅有与未来事件关联的实例,即不可与其他future<T>实例共享同一未来事件;而shared_future<T> 对象可以,可以多个实例共享着同一未来事件;
  • future<T>,shared_future<T>中的T表示未来事件关联数据的类型.若为void,则表明future<T>, shared_future<T>关联的未来事件没有数据.
  • future<T>,shared_future<T>对象是非线程安全的;即不能多个线程访问同一个数据对象.

创建 future 对象

async

  • async()创建的未来事件在其关联的函数执行完成后发生;并且此时未来事件的数据就是函数的返回值.

package_task

  • package_task<F>std::function<T>一致,其内保存着一个可执行对象,并且本身也是一个可执 行对象;模板参数F指定了其调用形式;如:

    /* 从 package_task 的定义可以看出;
     * o F 的参数列表指定了 package_task 的调用形式.
     * o F 的返回值类型指定了 package_task 关联 future 的模板参数;
     */
    struct package_task<int (int,int)> {
        void operator(int,int);
        std::future<int> get_future();
    };
    
  • 当调用package_task<F>对象时,会执行其内保存的函数对象,当其内保存的函数对象执行完成后,package_task<F> 关联的future<T>对象变为就绪状态.并且将返回值存放到future<T>中.

  • 此时package_task<F>创建的未来事件在package_task<F>对象被调用时发生;关联的数据就是 package_task<F>内保存的函数对象的返回值.

promise

  • promise<T>/future<T> 就像管道的写,读端;此时promise<T>创建的未来事件在调用promise<T>::set_value() 时发生,并且此时未来事件关联的数据就是set_value()的参数.

将异常保存在 future 对象中

  • async()在异步执行函数过程时发生了异常,则会将异常对象保存到关联的future<T>上.
  • package_task<F>在执行时发生了异常,则会将异常对象保存到关联的future<T>对象上.若package_task<F> 在被析构时仍未被执行,则也会将特定的异常对象保存到关联的future<T>对象上.
  • 通过调用promise<T>::set_exception()显式将异常对象保存到future<T>之上;若promise<T>对象在 被析构时仍未调用过set_value()set_exception(),则也会将一个特定的异常对象保存到关联的future<T>对象上.

创建 shared_future

  • 创建future对象,然后将该对象移动(future无法拷贝,只能移动)给shared_future对象.
  • 通过调用future<T>::share()函数得到shared_future对象.如:

    auto sf = future<T>::share();
    // 此时可以使用'auto'关键词省事.
    

有时间限制的等待

超时的指定

  • 相对时间;
  • 绝对时间;
  • 在 c++ 中,接受相对时间作为超时参数的函数一般以’_for’结尾.接受绝对时间作为超时参数的函数一般以 ‘_util’结尾.

C++ 时钟类

  • 在 C++ 中,时钟作为一个类存在,提供如下信息:
  • 时钟的当前值(当前时间);通过CLOCK::now()函数获取.
  • 时钟表示时间的类型;即:CLOCK::time_point
  • 时钟的节拍周期;即时钟走一拍所需要的时间;即:CLOCK::period;如:

    typedef std::ratio<5,2> period;
    // 这表明时钟在 5 秒内走 2 拍.即节拍周期为 2.5 秒.
    
    • 若时钟的节拍周期不固定;则period可能被定义为平均值,或者开发者认为合适的值.
  • 是否是匀速时钟;通过CLOCK::is_steady()确定;
    • 匀速时钟;以均匀的速率计时,并且不可被调整.

TODO

  • 4.3 节未看.

并发编程范式

FP;函数式编程

  • 纯函数;即函数的调用结果仅依赖函数的参数,不依赖任何外部状态;同时函数的调用结果仅作用在函数的返回 值上,不影响任何外部状态.

CSP;通信顺序处理

  • 其特点就是:线程之间完全独立;没有共享数据;但是具有可以传递消息的通信通道.

转载请注明出处!谢谢