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