C++多线程编程第十二讲--windows临界区、其他各种mutex互斥量
//(1)windows临界区
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
#include<windows.h>
#define _WINDOWS //定义一个开关
using namespace std;
class A
{
public:
A()
{
#ifdef _WINDOWS
InitializeCriticalSection(&my_winsec); //用临界区之前要先初始化
#endif // _WINDOWS
}
public:
//把收到的消息,入到一个队列中
void inMsgRecvQueue()
{
int i;
for (i = 0; i < 100000; ++i)
{
cout << "push_back num = " << i << endl;
//lock之后只能有一个线程可以对msgQueue队列做操作
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
msgQueue.push_back(i); //数字i就是玩家的命令。
LeaveCriticalSection(&my_winsec);
#else
my_mutex.lock();
msgQueue.push_back(i); //数字i就是玩家的命令。
my_mutex.unlock();
#endif //
}
}
bool outMsgProc(int& command)
{
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
LeaveCriticalSection(&my_winsec);
return true;
}
else
{
LeaveCriticalSection(&my_winsec);
return false;
}
#else
my_mutex.lock();
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
my_mutex.unlock();
return true;
}
else
{
my_mutex.unlock();
return false;
}
#endif
}
//把数据从消息队列中取出
void outMsgRecvQueue()
{
int i;
int command = 0;
for (i = 0; i < 100000; ++i)
{
int result = outMsgProc(command);
if (result == true)
{
cout << "command = " << command << endl;
}
else
{
cout << "msgQueue is empty" << endl;
}
}
}
private:
list<int> msgQueue;
mutex my_mutex; //创建一个互斥量
#ifdef _WINDOWS
CRITICAL_SECTION my_winsec; //windows下的临界区,非常类似C++的mutex
#endif // _WINDOES
};
int main()
{
A myobj;
thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象
thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
myOutMsg.join();
myInMsg.join();
cout << "main thread end..." << endl;
return 0;
}
//(2)多次进入临界区试验
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
#include<windows.h>
#define _WINDOWS //定义一个开关
using namespace std;
class A
{
public:
A()
{
#ifdef _WINDOWS
InitializeCriticalSection(&my_winsec); //用临界区之前要先初始化
#endif // _WINDOWS
}
public:
//把收到的消息,入到一个队列中
void inMsgRecvQueue()
{
int i;
for (i = 0; i < 100000; ++i)
{
cout << "push_back num = " << i << endl;
//lock之后只能有一个线程可以对msgQueue队列做操作
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
EnterCriticalSection(&my_winsec); //这是允许的,但是对应的离开也需要写两次
msgQueue.push_back(i); //数字i就是玩家的命令。
LeaveCriticalSection(&my_winsec);
LeaveCriticalSection(&my_winsec); //如果这个没有的话,相当于还是一直加着锁。
#else
my_mutex.lock();
//my_mutex.lock(); //会报错,和windows有区别
msgQueue.push_back(i); //数字i就是玩家的命令。
my_mutex.unlock();
#endif //
}
}
bool outMsgProc(int& command)
{
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
LeaveCriticalSection(&my_winsec);
return true;
}
else
{
LeaveCriticalSection(&my_winsec);
return false;
}
#else
my_mutex.lock();
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
my_mutex.unlock();
return true;
}
else
{
my_mutex.unlock();
return false;
}
#endif
}
//把数据从消息队列中取出
void outMsgRecvQueue()
{
int i;
int command = 0;
for (i = 0; i < 100000; ++i)
{
int result = outMsgProc(command);
if (result == true)
{
cout << "command = " << command << endl;
}
else
{
cout << "msgQueue is empty" << endl;
}
}
}
private:
list<int> msgQueue;
mutex my_mutex; //创建一个互斥量
#ifdef _WINDOWS
CRITICAL_SECTION my_winsec; //windows下的临界区,非常类似C++的mutex
#endif // _WINDOES
};
int main()
{
A myobj;
thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象
thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
myOutMsg.join();
myInMsg.join();
cout << "main thread end..." << endl;
return 0;
}
//(3)自动析构技术
// std::lock_guard<std::mutex> //自动加锁和解锁
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
#include<windows.h>
#define _WINDOWS //定义一个开关
using namespace std;
//自动加锁,自动释放锁的写法,类似与lock_guard的写法
class CWinLock
{
public:
CWinLock(CRITICAL_SECTION* _my_winsec) :my_winsec(_my_winsec)
{
EnterCriticalSection(my_winsec);
}
~CWinLock()
{
LeaveCriticalSection(my_winsec);
}
private:
CRITICAL_SECTION* my_winsec; //windows下的临界区,非常类似C++的mutex
};
class A
{
public:
A()
{
#ifdef _WINDOWS
InitializeCriticalSection(&my_winsec); //用临界区之前要先初始化
#endif // _WINDOWS
}
public:
//把收到的消息,入到一个队列中
void inMsgRecvQueue()
{
int i;
for (i = 0; i < 100000; ++i)
{
cout << "push_back num = " << i << endl;
//lock之后只能有一个线程可以对msgQueue队列做操作
#ifdef _WINDOWS
CWinLock clock(&my_winsec); //RAII的写法
msgQueue.push_back(i); //数字i就是玩家的命令。
#else
std::lock_guard<std::mutex> lock_g(my_mutex); //自动加锁,自动释放锁。以{}为范围
//my_mutex.lock();
//my_mutex.lock(); //会报错,和windows有区别
msgQueue.push_back(i); //数字i就是玩家的命令。
//my_mutex.unlock();
#endif //
}
}
bool outMsgProc(int& command)
{
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
LeaveCriticalSection(&my_winsec);
return true;
}
else
{
LeaveCriticalSection(&my_winsec);
return false;
}
#else
my_mutex.lock();
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
my_mutex.unlock();
return true;
}
else
{
my_mutex.unlock();
return false;
}
#endif
}
//把数据从消息队列中取出
void outMsgRecvQueue()
{
int i;
int command = 0;
for (i = 0; i < 100000; ++i)
{
int result = outMsgProc(command);
if (result == true)
{
cout << "command = " << command << endl;
}
else
{
cout << "msgQueue is empty" << endl;
}
}
}
private:
list<int> msgQueue;
mutex my_mutex; //创建一个互斥量
#ifdef _WINDOWS
CRITICAL_SECTION my_winsec; //windows下的临界区,非常类似C++的mutex
#endif // _WINDOES
};
int main()
{
A myobj;
thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象
thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
myOutMsg.join();
myInMsg.join();
cout << "main thread end..." << endl;
return 0;
}
//(4)recursive_mutex递归的独占互斥量
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
#include<windows.h>
//#define _WINDOWS //定义一个开关
using namespace std;
//自动加锁,自动释放锁的写法,类似与lock_guard的写法
class CWinLock
{
public:
CWinLock(CRITICAL_SECTION* _my_winsec) :my_winsec(_my_winsec)
{
EnterCriticalSection(my_winsec);
}
~CWinLock()
{
LeaveCriticalSection(my_winsec);
}
private:
CRITICAL_SECTION* my_winsec; //windows下的临界区,非常类似C++的mutex
};
class A
{
public:
A()
{
#ifdef _WINDOWS
InitializeCriticalSection(&my_winsec); //用临界区之前要先初始化
#endif // _WINDOWS
}
public:
//把收到的消息,入到一个队列中
void inMsgRecvQueue()
{
int i;
for (i = 0; i < 100000; ++i)
{
cout << "push_back num = " << i << endl;
//lock之后只能有一个线程可以对msgQueue队列做操作
#ifdef _WINDOWS
CWinLock clock(&my_winsec); //RAII的写法
msgQueue.push_back(i); //数字i就是玩家的命令。
#else
my_mutex.lock();
my_mutex.lock(); //会报错,和windows有区别
msgQueue.push_back(i); //数字i就是玩家的命令。
my_mutex.unlock();
my_mutex.unlock();
#endif //
}
}
bool outMsgProc(int& command)
{
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
LeaveCriticalSection(&my_winsec);
return true;
}
else
{
LeaveCriticalSection(&my_winsec);
return false;
}
#else
my_mutex.lock();
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
my_mutex.unlock();
return true;
}
else
{
my_mutex.unlock();
return false;
}
#endif
}
//把数据从消息队列中取出
void outMsgRecvQueue()
{
int i;
int command = 0;
for (i = 0; i < 100000; ++i)
{
int result = outMsgProc(command);
if (result == true)
{
cout << "command = " << command << endl;
}
else
{
cout << "msgQueue is empty" << endl;
}
}
}
private:
list<int> msgQueue;
//mutex my_mutex; //创建一个互斥量,是一个独占互斥量
//是一个递归的独占互斥量,在同一个线程内,可以多次lock,但也需要多次unlock,需要相对应
recursive_mutex my_mutex; //与windows中的CRITICAL_SECTION更像
#ifdef _WINDOWS
CRITICAL_SECTION my_winsec; //windows下的临界区,非常类似C++的mutex
#endif // _WINDOES
};
int main()
{
A myobj;
thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象
thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
myOutMsg.join();
myInMsg.join();
cout << "main thread end..." << endl;
return 0;
}
//(5)带超时的互斥量std::timed_mutex和std::recursive_timed_mutex
//try_lock_for() //等待一段时间
//try_lock_until() //未来的时间点
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
#include<windows.h>
//#define _WINDOWS //定义一个开关
using namespace std;
class A
{
public:
A()
{
#ifdef _WINDOWS
InitializeCriticalSection(&my_winsec); //用临界区之前要先初始化
#endif // _WINDOWS
}
public:
//把收到的消息,入到一个队列中
void inMsgRecvQueue()
{
int i;
for (i = 0; i < 100000; ++i)
{
cout << "push_back num = " << i << endl;
//lock之后只能有一个线程可以对msgQueue队列做操作
#ifdef _WINDOWS
CWinLock clock(&my_winsec); //RAII的写法
msgQueue.push_back(i); //数字i就是玩家的命令。
#else
if (my_mutex.try_lock_until(chrono::steady_clock::now()+100ms)) //等待100ms来判断是否拿到锁
{
msgQueue.push_back(i); //数字i就是玩家的命令。
my_mutex.unlock();
}
else
{
cout << "Do not get lock..." << endl;
}
#endif //
}
}
bool outMsgProc(int& command)
{
#ifdef _WINDOWS
EnterCriticalSection(&my_winsec);
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
LeaveCriticalSection(&my_winsec);
return true;
}
else
{
LeaveCriticalSection(&my_winsec);
return false;
}
#else
my_mutex.lock();
if (!msgQueue.empty())
{
//消息不为空
command = msgQueue.front();
msgQueue.pop_front(); //移除首元素
my_mutex.unlock();
return true;
}
else
{
my_mutex.unlock();
return false;
}
#endif
}
//把数据从消息队列中取出
void outMsgRecvQueue()
{
int i;
int command = 0;
for (i = 0; i < 100000; ++i)
{
int result = outMsgProc(command);
if (result == true)
{
cout << "command = " << command << endl;
}
else
{
cout << "msgQueue is empty" << endl;
}
}
}
private:
list<int> msgQueue;
std::timed_mutex my_mutex;
#ifdef _WINDOWS
CRITICAL_SECTION my_winsec; //windows下的临界区,非常类似C++的mutex
#endif // _WINDOES
};
int main()
{
A myobj;
thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象
thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj));
myOutMsg.join();
myInMsg.join();
cout << "main thread end..." << endl;
return 0;
}
posted on 2021-11-02 08:12 xcxfury001 阅读(79) 评论(0) 收藏 举报
浙公网安备 33010602011771号