c++并发初步学习(2)

在c++中,通过构造std::mutex的实例来创建互斥元,调用成员函数lock()来锁定他,调用unlock()来进行解锁。不过直接调用成员函数是不推荐的做法,因为这意味着你必须记住在每条可能离开函数(即线程)的代码路径上提供std::unlock(),包括由于异常所导致在内的。作为替代,c++提供了std::lock_guard类模板,实现了RAII惯用方法;它在构造函数时锁定互斥元,在析构是解锁互斥元,从而保证被锁定的互斥元始终被锁定和解锁。
然而,用互斥元保护数据并不只是像在每个成员函数中拍进一个std::lock_guard对象那样容易,一个迷路的指针或者引用,所有的保护都将白费。如下面的实例那样意外的传出对受保护数据的引用:

class some_data
{
private:
    int a;
    std::string b;
public:
    void do_something();
};

class data_wrapper
{
private:
    some_data data;
    std::mutex m;
public:
    template<typename Function>
    void process_data(Function func){
        std::lock_guard<std::mutex> l(m);
        func(data);         //传递“受保护的”数据到用户提供的函数
    }
};

some_data* unprotected;

void malicious_function(some_data& protected_data){
    unprotected = &protected_data;
}

data_wrapper x;

void foo(){
    x.process_data(malicious_function);
    unprotected->do_something();

在上面的实例中,process_data中的代码看似无害,受到std::lock_guard很好的保护,但对用户提供的函数func的调用就意味着foo可以传入malicious_function来绕过保护,然后无需锁定互斥元即可调用do_something()。
从根本上来说,这个代码的问题在于他没有完成你所设置的内容,标记所有访问该数据结构的代码为互斥的。在这个例子中,忽略了foo()中调用unprotected->do_something()的代码。不幸的是,这部分代码不是c++线程库所能帮助你的,而是取决于作为程序员的我们,去锁定正确的互斥元来保护你的数据。你有一个可遵循的准则:不要讲对受保护数据的指针和引用传递到锁的范围之外,无论是通过函数中返回他们、将其存放在外部可见的内存中,还是作为参数传递给用户提供的函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值