第三章 数据竞争与互斥对象

12 篇文章 0 订阅
10 篇文章 0 订阅

案例:

#include<iostream>

#include<string>

#include<thread>

  

using namespace std;

  

void function_1()

{

for (int i = 0; i > -100; i--)

{

std::cout << "From t1:" << i << std::endl;

  

}

}

int main()

{

thread t1(function_1);

for (int i = 0; i < 100; i++)

{

cout << "From main:" << i << endl;

}

t1.join();

}

输出

  

可以看到其中有Fromt1:From main:50

原因在于代码中的cout为两个线程共同竞争使用。解决的方法使用互斥对象来同步资源访问。

#include<iostream>

#include<string>

#include<thread>

#include<mutex>

  

using namespace std;

  

std::mutex mu;

  

void shared_Print(string msg,int id)

{

  

mu.lock();

std::cout << msg << id << endl;

mu.unlock();

  

}

void function_1()

{

for (int i = 0; i > -100; i--)

{

//std::cout << "From t1:" << i << std::endl;

//using shared_Print function instead of function_1

shared_Print("From t1", i);

  

}

}

int main()

{

thread t1(function_1);

for (int i = 0; i < 100; i++)

{

//cout << "From main:" << i << endl;

shared_Print("From Main()", i);

}

t1.join();

}

  

  

但是,这样使用下,有一种情况发生时将会造成死锁的发生。

在程序mu.lock与mu.unlock之间的函数如果抛出意外,此事程序将不能解锁,从而使得程序锁住。

  

使用另外一种方式来替代:

Std::lock_guard<std::mutex>guard(mu)

  

#include<iostream>

#include<string>

#include<thread>

#include<mutex>

  

using namespace std;

  

std::mutex mu;

  

void shared_Print(string msg,int id)

{

  

std::lock_guard<std::mutex> guard(mu);

std::cout << msg << id << endl;

  

  

}

void function_1()

{

for (int i = 0; i > -100; i--)

{

//std::cout << "From t1:" << i << std::endl;

//using shared_Print function instead of function_1

shared_Print("From t1", i);

  

}

}

int main()

{

thread t1(function_1);

for (int i = 0; i < 100; i++)

{

//cout << "From main:" << i << endl;

shared_Print("From Main()", i);

}

t1.join();

}

#end

另外一个问题来了,cout是全局型的,因此其他程序段可以继续使用cout,从而没有实现完全意义上的线程保护,。即没有在互斥量mu中作为私有函数供(绑定)使用。

使用类可以解决该问题。

#include<iostream>

#include<string>

#include<thread>

#include<mutex>

#include<fstream> //将数据保存到文件中使用fsteam头文件

  

using namespace std;

  

std::mutex mu;

class lofFile

{

public:

lofFile() //

{

f.open("log.txt");

}

void share_Print(std::string id, int value) //成员函数

{

std::lock_guard<mutex> locker(m_mutex);

f << "from " << id << value << endl;

}

protected:

private:

mutex m_mutex;

ofstream f;

};

  

void function_1(lofFile& l) //添加引用

{

for (int i = 0; i > -100; i--)

{

//std::cout << "From t1:" << i << std::endl;

//using shared_Print function instead of function_1

l.share_Print("From t1", i);

  

}

}

int main()

{

lofFile l;

thread t1(function_1, std::ref(l)); //一定注意添加引用

for (int i = 0; i < 100; i++)

{

//cout << "From main:" << i << endl;

l.share_Print("From Main()", i);

}

t1.join();

}

找到文件夹下的文件

清单3.2 无意中传递了保护数据的引用

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;

}

data_wrapper x;

void foo()

{

x.process_data(malicious_function); // 2 传递一个恶意函数

unprotected->do_something(); // 3 在无保护的情况下访问保护数据

}

  

例子中process_data看起来没有任何问题, std::lock_guard 对数据做了很好的保护,但调用用户提供的函数func①,就意味着foo能够绕过保护机制将函数 malicious_function 传递进去②,在没有定互斥量的情况下do_something()

  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值