Boost 第十二章 并发编程

本文章所有内容源于《BOOST程序库完全开发指南:深入C++“准”标准库(第3版)》第十二章


本章内容包括Boost库中的三个并发编程组件。atomic,它实现了C++11标准定义的原子操作库;thread,它兼容了C++11标准,为C++增加了可移植的线程处理能力;asio,用于同步和异步IO操作的功能强大的库,使用前摄器模式,可以处理口、网络通信,而且有望成为C++标准底层通信库。

1. atomic

1.1 功能:

本节代码都是单线程的,没有并发。

1.2 头文件:

#include<boost/atomic.hpp>
using namespace boost;

1.3 用法:

#include "/home/fjc/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;

#include <boost/atomic.hpp>
using namespace boost;


//
void case1()
{
    atomic<int> a(10);  //记住这里的构造方法
    assert(a == 10);
    //不要缺省构造很危险:atomic<int> a;
    
    atomic<double> l;
    l = 100L;
    cout << l << endl;

    atomic<double> d(2.414);
    cout << d << endl;
    cout << "--------------"<<endl;
}

void case2()
{
    atomic<bool> b{false};          //原子化bool
    assert(!b.load());                      //显示调用load取值

    b.store(true);                              //显示调用store
    assert(b);                                       //隐士类型转换,等价于load

    atomic<int> n(100);                                   //原子化int
    assert(n.exchange(200) == 100);                 //存储的同时返回原始值
    assert(n == 200);                                   //隐式类型转换,等价于load

    cout << "--------------"<<endl;
}
//
void case3()
{
    atomic<long> l(100);                

    long v = 100;               //设置变量expected,左值
    if (l.compare_exchange_weak(v, 313))            //比较并交换
    {
        assert(l == 313 && v == 100);       //如果成功值改变,输出原值100
    }

    v = 200;                                                    //设置变量expected=200
    auto b = l.compare_exchange_strong(v, 99);          //比较并交换
    assert(!b && v == 313);                                                     //交换失败,输出原值313

    l.compare_exchange_weak(v, 99);         //再次比较交换
    assert(l == 99 && v == 313 );
    cout << "--------------"<<endl;
}

//
#include <boost/utility.hpp>
void case4()
{
    atomic<int> n(100);

    assert(n.fetch_add(10) == 100);
    assert(n == 110);

    assert(++n == 111);
    assert(n++ ==111);
    assert(n == 112);

    assert((n -= 10) == 102);

    atomic<int> b{BOOST_BINARY(1101)};      //二进制1101

    auto x = b.fetch_and(BOOST_BINARY(0110));   //逻辑与运算,返回原始数值1101
    assert(x == BOOST_BINARY(1101) &&
           b == BOOST_BINARY(0100));                        //b运算后是0100
    assert((b |= BOOST_BINARY(1001))                //相当于fetch_or,返回运算后数值
            == BOOST_BINARY(1101));
}

//
void case5()
{
    atomic<bool> b{true};
    assert(b);

    b = false;
    assert(!b.load());

    auto x = b.exchange(true);
    assert(b && !x);
}
//
#include <boost/intrusive_ptr.hpp>

template<typename T>
class ref_count			//泛型引用计数类
{
private:
    typedef boost::atomic<int> atomic_type; //定义atomic类型
    mutable atomic_type m_count{0};	//初始化注意是mutable
protected:
    ref_count() {}
    ~ref_count() {}
public:
    typedef boost::intrusive_ptr<T> counted_ptr;
    void add_ref() const            //增加引用计数
    {
        m_count.fetch_add(1, boost::memory_order_relaxed); //不做任何顺序要求
    }

    void sub_ref() const		//减少引用计数
    {
        if (m_count.fetch_sub(1, boost::memory_order_release) == 1)
        {
            boost::atomic_thread_fence(boost::memory_order_acquire);//原子级别线程保护,获取之前的修改
            delete static_cast<const T*>(this);								//删除指针,需要转型
        }
    }

    decltype(m_count.load()) count() const			//获取引用计数,注意decltype
    {
        return m_count.load();			//取值也可以用隐士类型转换
    }

public:
    template<typename ... Args>			//可变参数模板
    static counted_ptr make_ptr(Args&& ... args)  			//工厂函数
    {
        return counted_ptr(new T(std::forward<Args>(args)...));
    }
private:
    friend void intrusive_ptr_add_ref(const T* p)		//要求函数
    {
        p->add_ref();
    }
    friend void intrusive_ptr_release(const T* p)		//要求函数
    {
        p->sub_ref();
    }
};

class demo: public ref_count<demo>	//添加引用计数能力
{
public:
    demo()
    {
        cout << "demo ctor" << endl;
    }
    ~demo()
    {
        cout << "demo dtor" << endl;
    }
    int x;
};
void case6()
{
    //demo::counted_ptr p(new demo);
    auto p = demo::make_ptr();

    p->x = 10;
    assert(p->x == 10);
    assert(p->count() == 1);
}
//

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
}

2. thread

2.1 功能:

需要chrono库提供的时间概念来执行水面、等待操作,需要先编译chrono库

2.2 头文件:

#include<boost/thread.hpp>
using namespace boost;

2.3 用法:

2.3.1 mutex:

mutex:
互斥量(mutex)是一种用于线程同步的手段,可以防止多个线程同时操作共享资源。一旦一个线程锁住了互斥量,那么其他线程必须等待它解锁互斥量后才能再访问共享资源

timed_mutex:
如果不想因为mutex而阻塞线程,那么就可以使用timed_mutex,调用它的try_lock_for()或try_lock_until(),等待一个相对或者绝对时间

2.3.2 lock_guard:

用于辅助锁定互斥量。构造时锁定,析构时解锁,避免遗忘解锁,像是一个智能指针

2.3.3 unique_lock:

与lock_guard类似,它的构造函数可以接收其他的锁定选项,从而有不同的行为。unique_lock不允许拷贝,但它内部使用指针而不是引用来保存互斥量,这使得它可以被转移,用起来更灵活。

2.3.4 lock适配器:

lock_guard、unique_lock通常搭配mutex使用。适配器类需要在模板参数里指定要适配的mutex类型,以继承的方式使用,子类自动获得他们的lock接口,然后就可以用locak_guard和unique_lock。

2.3.5 lockable概念检查类:

2.3.6 lock函数:

除了使用mutex的成员函数或者lock_guard/unique_lock,还可以使用两个自由函数lock()和try_lock()来操作mutex,它们类似make_unique_locks(),可以一次锁定多个互斥量,而且保证不会出现死锁

2.3.7 thread:

thread类实现了操作系统里的线程表示,负责启动和管理线程对象,在概念和操作上都与POSIX线程相似。
四个静态函数:
get_id():同thread的同名函数,用来获得thread::id
yield():指示当前线程放弃时间片,允许其他的线程运行
sleep_for():线程睡眠等待一个小段时间
sleep_until():线程睡眠等待至一个时间点

2.3.8 启动线程:

线程启动可以用bind或者lambda表达式

thread t1(bind(dummy,100));
thread t2([]{dummy(500);});

sleep_for是在死等线程,因此有join等待线程。thread的成员函数joinable()可以判断thread对象是否标识了一个可执行的线程体。如果joinable()返回true,我们就可以调用成员函数join来阻塞等待线程执行结束

detach分离线程:临时对象启动线程,与线程执行体分离,但线程继续运行
thread_guard:用于控制thread对象析构的行为
scoped_thread:它可以使用模板参数定制析构的动作

2.3.9 中断线程:

interrupt():要求线程中断执行
interruption_requested():检查线程是否被要求中断

线程的12个中断点
启用/禁用线程中断

2.3.10 thread_group:

用于管理一组线程,就像是一个线程池

2.3.11 call_once:

为了保证在多线程环境中初始化函数可被正确调用,thread库提供了仅调用一次的机制,使用多个线程在操作函数时,只能又一个线程成功执行,避免多次执行导致错误。以once_flag对象作为初始化标志,再使用call_once来调用函数,完成仅执行一次的初始化

2.3.12 条件变量:conditon

条件变量是另一种用于等待的同步机制,可以实现线程间的通信,它必须与互斥量配合使用,等待另一个线程中某个事件的发生(满足某个条件),然后才可以继续执行。

2.3.13 shared_mutex:

它允许线程获取多个共享所有权和一个专享所有权,实现了读写锁的机制,即多个读线程一个写线程

2.3.14 future:

很多情况下线程不仅仅要执行一些工作,它还可能要返回一些计算结果。thread库使用future提供了异步操作线程返回值的方法,因为这个返回值在线程开始执行似乎还是不可用的,是一个“未来”的“期待值”

2.3.15 shared_future:

多次调用future

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值