103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <thread>
 | 
						||
#include <mutex>
 | 
						||
#include <queue>
 | 
						||
#include <iostream>
 | 
						||
using namespace std;
 | 
						||
#define LOOP_TIMES 100
 | 
						||
void test1() {
 | 
						||
	mutex mtx;
 | 
						||
	int res = 0;
 | 
						||
	thread t1([&]() {
 | 
						||
		for (int i = 0; i < LOOP_TIMES;i++) {
 | 
						||
			this_thread::sleep_for(chrono::milliseconds(1));
 | 
						||
			res = res + 1;
 | 
						||
		}
 | 
						||
	});
 | 
						||
	thread t2([&]() {
 | 
						||
		for (int i = 0; i < LOOP_TIMES; i++) {
 | 
						||
			this_thread::sleep_for(chrono::milliseconds(1));
 | 
						||
			mtx.lock();
 | 
						||
			res = res - 1;
 | 
						||
			mtx.unlock();
 | 
						||
		}
 | 
						||
	});
 | 
						||
	t1.join();
 | 
						||
	t2.join();
 | 
						||
	std::cout << "test1:: res:: " << res  << " mutexsize::" << sizeof(mutex) << endl;
 | 
						||
}
 | 
						||
void test2() {
 | 
						||
	recursive_mutex mtx;
 | 
						||
	int res = 0;
 | 
						||
	thread t1([&]() {
 | 
						||
		for (int i = 0; i < LOOP_TIMES / 10; i++) {
 | 
						||
			this_thread::sleep_for(chrono::milliseconds(i));
 | 
						||
			lock_guard<recursive_mutex> lock(mtx);
 | 
						||
			res = res + 1;
 | 
						||
		}
 | 
						||
	});
 | 
						||
	thread t2([&]() {
 | 
						||
		for (int i = 0; i < LOOP_TIMES / 10; i++) {
 | 
						||
			this_thread::sleep_for(chrono::milliseconds(i));
 | 
						||
			unique_lock<recursive_mutex> lock(mtx);
 | 
						||
			res = res - 1;
 | 
						||
		}
 | 
						||
	});
 | 
						||
	t1.join();
 | 
						||
	t2.join();
 | 
						||
	std::cout << "test2:: res:: " << res << " lock_guard::" << sizeof(lock_guard<mutex>)
 | 
						||
		<< " unique_lock::" << sizeof(unique_lock<mutex>) << endl;
 | 
						||
}
 | 
						||
void test3() {
 | 
						||
	mutex mtx;
 | 
						||
	int res = 0;
 | 
						||
	int error_count = 0;
 | 
						||
	queue<int> mq;
 | 
						||
	thread t1([&]() {
 | 
						||
		for (int i = 0; i < LOOP_TIMES; i++) {
 | 
						||
			this_thread::sleep_for(chrono::milliseconds(i));
 | 
						||
			lock_guard<mutex> lock(mtx);
 | 
						||
			mq.push(i / 2);
 | 
						||
			res = res + 1;
 | 
						||
		}
 | 
						||
	});
 | 
						||
	thread t2([&]() {
 | 
						||
		int a = 0;
 | 
						||
		for (int i = 0; i < LOOP_TIMES;) {
 | 
						||
			this_thread::sleep_for(chrono::milliseconds(a));
 | 
						||
			unique_lock<mutex> lock(mtx);
 | 
						||
			if (mq.empty()) {
 | 
						||
				error_count++;
 | 
						||
				continue;
 | 
						||
			}
 | 
						||
			i++;
 | 
						||
			a = mq.front();
 | 
						||
			mq.pop();
 | 
						||
			res = res - 1;
 | 
						||
		}
 | 
						||
	});
 | 
						||
	t1.join();
 | 
						||
	t2.join();
 | 
						||
	std::cout << "test3:: res:: " << res << " error_count::" << error_count << endl;
 | 
						||
}
 | 
						||
int main() {
 | 
						||
	/*
 | 
						||
		进程是房子,线程是住在房子里的人,厕所、厨房...是房子里的共享资源。
 | 
						||
	*/
 | 
						||
	test1();
 | 
						||
	test2();
 | 
						||
	/*
 | 
						||
	mutex 原子性 排队性
 | 
						||
	//保证资源的正确使用,如一个厕所只能一个人用
 | 
						||
		//递归锁可以让前面的人重复上锁,避免函数递归时解锁出错
 | 
						||
	//排队等待前一个人离开,才能使用
 | 
						||
		//超时锁,可以先进入自旋,超时后阻塞
 | 
						||
	*/
 | 
						||
	test3();
 | 
						||
	/* 
 | 
						||
		锁 如果存在单向依赖,无法保证资源是否存在,会空转CPU
 | 
						||
		生产者知道什么时候有资源,消费者知道什么时候没有资源
 | 
						||
		消费者上锁等待,生产者解锁通知, 锁只能自己锁自己解锁
 | 
						||
	*/
 | 
						||
	
 | 
						||
	return 0;
 | 
						||
} |