C++ multi-threaded learning (thirteen, simple thread-safe stack encapsulation)

Table of contents

Simple thread-safe stack wrapper

Why doesn't the code above unlock?

Why is the output not 0


Simple thread-safe stack wrapper

#include <iostream>
#include <thread>
#include <mutex>
#include <stack>
#include <vector>
#include <exception>
using namespace std;
//异常处理
struct Stack_Empty :public exception
{
	//重写了exception类中的what()函数,用于返回异常信息。
	const char* what() const noexcept
	{
		return "栈为空";
	}
};
//简单的线程安全栈的封装
template<class T>
class Thread_Safe_Stack
{
public:
	Thread_Safe_Stack() {}
	Thread_Safe_Stack(const Thread_Safe_Stack& other)
	{
		lock_guard<mutex> lock(other.mtx);
		this->data = other.data;
	}
	//复制赋值运算符禁用
	Thread_Safe_Stack& operator=(const Thread_Safe_Stack&) = delete;
	//常用函数
	bool isEmpty()
	{
		lock_guard<mutex> lock(mtx);
		return data.empty();
	}
	size_t theSize()
	{
		lock_guard<mutex> lock(mtx);
		return data.size();
	}
	//存取数据
	void PushData(T value)
	{
		lock_guard<mutex> lock(mtx);
		data.push(value);
		printf("insertValue:%d\n", value);
	}
	void getData(T& value)
	{
		lock_guard<mutex> lock(mtx);
		if (data.empty())//如果是空的则抛出异常
		{
			throw Stack_Empty();
		}
		else
		{
			value = data.top();
			data.pop();
		}
	}
private:
	mutable mutex mtx;
	stack<T> data;
};
//测试函数
void insertData(Thread_Safe_Stack<int>& stack, int data)
{
	stack.PushData(data);
}
void popData(Thread_Safe_Stack<int>& stack)
{
	try
	{
		int value = 0;
		stack.getData(value);
		printf("data:%d\n", value);
	}
	catch(Stack_Empty one)//为空捕获
	{
		printf("%s\n", one.what());
	}
}

int main()
{
	vector<thread> t;
	Thread_Safe_Stack<int> test;
	for (int i = 0; i < 5000; i++)
	{
		t.push_back(thread(insertData, ref(test), i));
		t.push_back(thread(popData, ref(test)));
	}
	for (auto& v:t)//线程是禁止拷贝的,所以用&
	{
		v.join();
	}

	cout << "size:" << test.theSize() << endl;
	return 0;
}

Why doesn't the code above unlock?

Lock_guard<mutex> lock(mtx) is used in the constructor and member functions , which is a RAII (Resource Acquisition Is Initialization) technology [ resource acquisition is initialization ], it will lock the mutex when it is constructed, and it will be destroyed when it is destroyed Automatically unlocks the mutex. So no need to manually unlock.

Why is the output not 0

If the result of the final output size is not 0 , assuming it is 29 , it means that after the multi-threaded insert and pop operations, the remaining number of elements in the stack is 29 . This may be due to a race condition between insert and pop operations where some data was popped by other threads, but 29 more data remained on the stack .

Guess you like

Origin blog.csdn.net/q244645787/article/details/131626393