《C++ Concurrency in Action》笔记7 mutex(1)

来源:互联网 发布:淘宝客导购推广位 编辑:程序博客网 时间:2024/06/05 04:52

C++标准库提供了std::mutex类作为互斥量,提供了lock()和unlock()成员函数,但是不建议直接使用这两个成员函数。如果漏写其中之一将导致错误,包括产生异常时的处理,都很容易出错。C++提供了一个类模板std::lock_guard,它对一个mutex实现了RAII机制,在构造时锁定mutex,析构时解锁mutex。保证在绝大多数情况下每一次lock都对应一个unlock。

一个不成熟的示例代码:

list<int> some_list;mutex some_mutex;void add_to_list(int new_value){lock_guard<mutex> guard(some_mutex);some_list.push_back(new_value);}bool list_contains(int value_to_find){lock_guard<mutex> guard(some_mutex);return find(some_list.begin(), some_list.end(), value_to_find) != some_list.end();}

上边代码中将mutex和与其关联的list定义成全局对象,一般来说不建议这样。

This is a standard application of objectoriented design rules: by putting them in a class, you’re clearly marking them as related, and you can encapsulate the functionality and enforce the protection.

一个标准的面向对象的设计原则是:将它们放在类里,你可以清晰的将mutex和其关联的( 被保护的)对象对应起来,将lock和unlock封装到函数里。

但是仍然有漏洞,如果一个成员函数返回了一个被保护对象的指针或引用,则这个指针或引用可以被外部代码拿来做修改操作,脱离了原本精心设计的保护机制。

Protecting data with a mutex therefore requires careful interface design, to ensure that the mutex is locked before there’s any access to the protected data and that there are no backdoors.

使用mutex需要小心设计接口,确保没有给外部留后门。这其中就包括,不能返回被保护对象的指针或引用,包括成员函数传出的参数。还有一种情况是,不能将指针或引用传给一个本身无法控制的外部函数。这些外部函数有可能保存了指针或者引用,然后在稍后去使用它,这样你无论如何也不能确保这些数据处于保护机制中。就像下面的代码这样:

class some_data{int a;string b;public:void do_something() {};};class data_wrapper{private:some_data data;mutex m;public:template<typename Function>void process_data(Function func){lock_guard<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();//处于未保护状态}

data_wrapper的函数process_data()将一个数据引用传给了外部函数malicious_function(),而外部函数缺将这个引用的指针记录下来,并在稍后缺乏mutex保护的情况下使用了。C++标准在这方面没有提供有帮助的手段,只能避免这种情况。


阅读全文
0 0
原创粉丝点击