版权声明:所有的博客都是博主的个人笔记。。。。。 https://blog.csdn.net/qq_35976351/article/details/84062558
共享数据的问题
这些在操作系统中都有详细的介绍,可以回顾操作系统课程。。很典型的就是数据竞争问题。
互斥量保护数据
最原始的方式:使用std::mutex
创建互斥量,使用成员lock()
加锁,使用成员unlock()
解锁。但是这种方式需要我们在每个函数出口都调用一次unlock()
,过于繁琐。。。
实例:
// std::lock example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::lock
std::mutex foo,bar; // 全局锁
void task_a () {
// foo.lock(); bar.lock(); // replaced by:
std::lock (foo,bar);
std::cout << "task a\n";
foo.unlock();
bar.unlock();
}
void task_b () {
// bar.lock(); foo.lock(); // replaced by:
std::lock (bar,foo);
std::cout << "task b\n";
bar.unlock();
foo.unlock();
}
int main ()
{
std::thread th1 (task_a);
std::thread th2 (task_b);
th1.join();
th2.join();
return 0;
}
/*
输出结果:
task a
task b
*/
一般使用std::lock_guard
模板类,在构造的时候对互斥量加锁,析构时解锁。
#include <iostream>
#include <mutex>
#include <thread>
#include <stdexcept>
std::mutex mtx;
void print_even(int x) {
if(x % 2 == 0)
std::cout << x << " is even\n";
else
throw (std::logic_error("not even"));
}
void print_thread_id(int id) {
try {
std::lock_guard<std::mutex>lck(mtx); // 函数结束时,自动析构解锁
print_even(id); // 相当于在这里加锁了
} catch(std::logic_error&) {
std::cout << "[exception caught]\n";
}
}
int main() {
std::thread threads[10];
for(int i = 0; i < 10; ++i) {
threads[i] = std::thread(print_thread_id, i + 1);
}
for(auto& th : threads)
th.join();
}
预防死锁
一般都是编程时候进行考虑的。。。方法留作后续补充。。操作系统上的思想为指导。
注意合理组织代码
C++中,如果是直接对地址进行操作,那么锁无法阻止这种行为。
class some_data
{
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); // 1 传递“保护”数据给用户函数
}
};
some_data* unprotected;
void malicious_function(some_data& protected_data)
{
unprotected=&protected_data; // 这里直接获取地址,那么unprotected的操作无法被锁限制
}
data_wrapper x;
void foo()
{
x.process_data(malicious_function); // 2 传递一个恶意函数
unprotected->do_something(); // 3 在无保护的情况下访问保护数据
}
因此代码中尽量避免直接对临界区的数据进行地址操作。