50 C++ 多个线程共享资源问题fix方案二 ----- lock_guard类

前提:

在上一节中,我们使用了mutex的lock函数和unlock函数处理共享资源问题

这一节,我们学习使用 lock_guard来处理 共享资源问题。

lock_guard是啥?

是个类模版,这个类模版只能对mutex类型进行构造

例子:

lock_guard mylock_guard(mymutex);

50 C++ 多个线程共享资源问题fix方案二 ----- lock_guard类_第1张图片

lock_guard的优点:

优点类似于智能指针,

当我们实例化一个 lock_guard后,不需要unlock()

lock_guard mylock_guard(mymutex);

lock_guard工作原理

lock_guard是个类,那么就有构造函数和析构函数。

lock_guard的构造函数里面 执行了 mutex::lock();

lock_guard的析构函数里面 指向了 mutex::unlock();

这也是lock_guard类只用 实例化出来,就不会unlock()的原因,因为当lock_guard 对象析构的时候,会自动的unlock();

这也意味着在实现时,要特别注意lock_guard 对象是什么时候析构的。必要的时候,可以用{}包装起来。

lock_guard 实例

改动代码如下:

class Teacher166 {

public:
	//共享数据 存在list中
	list msgListQueue;
	mutex mymutex;
	int readcount = 0;//记录已经读取了多少个。
public:
	//读取 共享数据的线程方法
	void readfunc() {
		while (true) {
			//只要不为空,就可以读取数据
			if (readcount >= 2000) {
				break;
			}
			lock_guard mylock_guard(mymutex);//mylock_guard在这里创建出来,在mylock_guard的构造函数中,就已经对mymutex进行了lock()操作,等到mylock_guard的生命周期结束后会析构,这时候会调用mymutex的unlock()函数
			if (!msgListQueue.empty()) {
				int readvalue = msgListQueue.front();//每次都读取第一个
				cout << "读取到的值为" << readvalue << " readcount = " << readcount << endl;
				msgListQueue.pop_front();//删除第一个元素
				readcount++;
			}
			else {
				cout << "没有读取到值" << endl;
			}
		}
	}

	//写入 共享数据的线程方法
	void writefunc() {
		for (size_t i = 0; i < 1000; i++)
		{
			lock_guard mylock_guard(mymutex);//mylock_guard在这里创建出来,在mylock_guard的构造函数中,就已经对mymutex进行了lock()操作,等到mylock_guard的生命周期结束后会析构,这时候会调用mymutex的unlock()函数,实际上这里实例化对象 lock_guard 不管名字是啥,只要里面参数是 mymutex就可以了,也就是说:只要是同一个 mutex
			msgListQueue.push_back(i);//每次都写到末尾
			cout << "写入元素的值为" << i << endl;
		}
	}

public:
	Teacher166() {
		cout << "Teacher166 构造方法 this = " << this << endl;
	}

	Teacher166(const Teacher166 & obj) {
		cout << "Teacher166 copy 构造方法 this = " << this << "  obj = " << &obj << endl;
	}

	~Teacher166() {
		cout << "Teacher166 析构函数 this = " << this << endl;
	}
};


void main() {

	cout << "=========================" << endl;

	Teacher166 tea1;

	thread readthread1(&Teacher166::readfunc, &tea1);
	thread writethread1(&Teacher166::writefunc, &tea1);
	//thread 的构造方法第二个参数 可以是地址,如果是地址,那么 readthread1 和 writethread1的传递就是同一个 teacher

	thread readthread2(&Teacher166::readfunc, &tea1);
	thread writethread2(&Teacher166::writefunc, &tea1);
	readthread1.join();
	readthread2.join();
	writethread1.join();
	writethread2.join();
}

你可能感兴趣的:(c++)