在对共享数据进行保护时,有可能被外界的指针修改。如下例:
#include<iostream>
#include<thread>
#include<mutex>
#include<windows.h>
using namespace std;
class user_data
{
public:
int a;
char c;
void change_data(void) { a *= 10; c += 10; }
};
user_data* unprotected_pt;
void function(user_data &mydata)
{
unprotected_pt = &mydata;
}
class protect_data
{
private:
user_data data;//保护里面的共享数据
mutex guard_mutex;
public:
protect_data() { data.a = 1; data.c = 'A'; }
void process_data(void)
{
lock_guard<mutex> guard(guard_mutex);//相当于加锁操作
data.a += 10;
data.c += 1;
function(data);
Sleep(5000);
}
void print(void)
{
cout << "data = " << data.a << " data.c = " << data.c << endl;
}
};
void thread_function(protect_data &pd);
int main(void)
{
protect_data pd;
pd.print();
thread t1(thread_function,ref(pd));
thread t2(thread_function,ref(pd));
t1.join();
t2.join();
pd.print();
return 0;
}
void thread_function(protect_data &pd)
{
pd.process_data();
}
这样看上去是没什么问题,将变量卡在私有接口上上,并且用锁将变量卡到一个进程中。但是:这里有一个游离的指针可以访问。如下:
用游离指针实现了修改,这是我们不想要的。因为function(data)将锁所在的作用域范围之外传递了引用和指针。
这种方法并没有被制止的方法,只能让我们写代码时不要这样做。
不要将受保护资源以函数指针或引用的方式将其传递在作用域之外。