c++多线程thread操作(三)数据竞争互斥访问

c++多线程系列

c++多线程thread操作(一)环境部署

c++多线程thread操作(二)线程管理

c++多线程thread操作(三)数据竞争互斥访问

c++多线程thread操作(四)死锁的问题和解决

c++多线程thread操作(五)unique_lock加锁

c++多线程thread操作(六)条件变量的使用

c++多线程thread操作(七)父进程获取子进程变量的结果

c++多线程thread操作(八)父线程传递数据给子线程

c++多线程thread操作(九)可调用方式

(终)c++多线程thread操作(十)多线程并行实现数据相加的和

1. 数据竞争问题:对共享资源的访问会出现杂乱无序的结果

void shared_print(string msg, int id) {
    cout << "From" << id << " : " << msg << endl;// cout是可竞争资源, 需要同步cout
}
void func_1() {
	for (int i = 0; i > -5; i--) {
		shared_print("From t1: ",i); // 
	}
}
int main() {
	thread t1(func_1); 
	for (int i = 0; i < 5; i++) {
		shared_print("From main: ", i);
	}
	t1.join();
	return 0;
}

 

2. 解决竞争问题:加上mutex锁

mutex mu;
void shared_print(string msg, int id) {
    mu.lock();
    cout << "From" << id << " : " << msg << endl;//如果这行发生了异常,mu锁将永远被锁住
    mu.unlock();
}
void func_1() {
	for (int i = 0; i > -5; i--) {
		shared_print("From t1: ",i); // 
	}
}
int main() {
	thread t1(func_1); 
	for (int i = 0; i < 5; i++) {
		shared_print("From main: ", i);
	}
	t1.join();
	return 0;
}

但如果mu.lock和mu.unlock之间抛出了异常,mu将永远被锁住!所有使用lock_guard锁来代替,只要lock_guard执行了析构函数,就会自动释放锁!

3. lock_guard代替mutex(建议不用Mutex,用lock_guard)

mutex mu;
void shared_print(string msg, int id) {
    lock_guard<mutex> guard(mu);// guard析构时自动释放锁
    cout << "From" << id << " : " << msg << endl;
}

但仍然有问题:cout是可竞争资源,多个线程可以共享使用,仍然达不到线程安全,考虑使用包装类加上ofstream流进行输出。

4. 类的实现,可作为模板使用:

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;
class LofFile {
public:
	LofFile() {
		f.open("log.txt");
	}
	void shared_print(string msg, int id) {
		lock_guard<mutex> guard(m_mutex);// guard析构时自动释放锁
		f << "From" << id << " : " << msg << endl;
	}
        //ofstream&GetStream() { return f; }// 这个是不安全的,f会暴露在函数外
	//void processf(void fun(ofstream&)) {
	//	fun(f);// f也会暴露在类外,会造成线程不安全
	//}
private:
	mutex m_mutex;
	ofstream f;// 线程安全的f
};
void func_1(LofFile&log) { 
	for (int i = 0; i > -10; i--) {
		log.shared_print("From t1: ", i);
	}
}
int main() {
	LofFile log;
	thread t1(func_1,ref(log)); 
	for (int i = 0; i < 10; i++) {
		log.shared_print("From main: ", i);
	}
	t1.join();
	return 0;
}

但要注意,ofstream不能暴露在类的外面,否则不能实现完全线程安全。如上述代码的注释!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值