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;
							 | 
						|||
| 
								 | 
							
								}
							 |