一、windows临界区 Windows 临界区:(使用前必须初始化)
CRITICAL_SECTION my_winsec;
InitializeCriticalSection(&my_winsec);
EnterCriticalSection(&my_winsec);
myQueue.push_back(i);
LeaveCriticalSection(&my_winsec);
二、windows临界区与C++ 11锁的异同:
关于Windows 临界区完整实例代码:
#include<mutex>
#include<Windows.h>
using namespace std;
#define __WINDOWSJQ_
class A
{
public:
void inMsg()
{
for (size_t i = 0; i < 100000; i++)
{
#ifdef __WINDOWSJQ_
EnterCriticalSection(&my_winsec);
EnterCriticalSection(&my_winsec);
myQueue.push_back(i);
LeaveCriticalSection(&my_winsec);
LeaveCriticalSection(&my_winsec);
#else
myLock.lock();
myQueue.push_back(i);
myLock.unlock();
#endif
cout << "--- 插入一个命令 ---" << endl;
}
return;
}
bool outLULProc(int command)
{
#ifdef __WINDOWSJQ_
EnterCriticalSection(&my_winsec);
if (!myQueue.empty())
{
command = myQueue.front();
myQueue.pop_front();
LeaveCriticalSection(&my_winsec);
return true;
}
LeaveCriticalSection(&my_winsec);
#else
myLock.lock();
if (!myQueue.empty())
{
command = myQueue.front();
myQueue.pop_front();
myLock.unlock();
return true;
}
myLock.unlock();
#endif
return false;
}
void outMsg()
{
for (size_t i = 0; i < 100000; i++)
{
int command = 0;
bool result = outLULProc(command);
if (result)
cout << "取出一个命令" << endl;
else
cout << "命令队列为空" << endl;
}
}
A()
{
#ifdef __WINDOWSJQ_
InitializeCriticalSection(&my_winsec);
#endif
}
private:
std::deque<int>myQueue;
std::mutex myLock;
#ifdef __WINDOWSJQ_
CRITICAL_SECTION my_winsec;
#endif
};
int main()
{
A myobj;
std::thread t1(&A::outMsg, std::ref(myobj));
std::thread t2(&A::inMsg, std::ref(myobj));
t1.join();
t2.join();
return 0;
}
三、自动析构技术: 在Windows 临界区中没有类似于C++ 11 中的std::lock_guard 的自动管理临界区上锁与取消锁的API ,可以根据其特点手写一个:
class CWinLock
{
public:
CWinLock(CRITICAL_SECTION *CS)
{
m_CS = CS;
EnterCriticalSection(m_CS);
}
~CWinLock()
{
LeaveCriticalSection(m_CS);
}
private:
CRITICAL_SECTION* m_CS;
};
使用:
CRITICAL_SECTION my_winsec;
CWinLock cw(&my_winsec);
myQueue.push_back(i);
四、递归独占互斥量 std::recursive_mutex (允许同一线程中多次lock() ):
std::mutex 独占式互斥量,不允许多次上lock() std::recursive_mutex :允许在同一个线程中同一个互斥量多次被 lock() ,(但是递归加锁的次数是有限制的,太多可能会报异常),效率要比std::mutex 低。
如果你真的用了 recursive_mutex 要考虑代码是否有优化空间,如果能调用一次 lock()就不要调用多次。
声明:
private:
std::recursive_mutex myreLock;
使用:(可以在同一线程中为代码片段上多次锁)
myreLock.lock();
myreLock.lock();
myQueue.push_back(i);
myreLock.unlock();
myreLock.unlock();
五、带超时功能的互斥量 std::timed_mutex 和 std::recursive_timed_mutex : 5.1 std::timed_mutex :
try_lock_for() :等待一段时间,超时没拿到锁则停止阻塞,不再等待。 例如:
std::chrono::milliseconds timed(100);
if (myLock.try_lock_for(timed))
{
myQueue.push_back(i);
myLock.unlock();
}
else
{
std::chrono::milliseconds sleeptime(100);
std::this_thread::sleep_for(sleeptime);
}
try_lock_until() :参数是一个未来的时间点,在这个未来的时间没到的时间内,如果拿到了锁头,流程就走下来,如果时间到了没拿到锁,流程也可以走下来。 例如:
std::chrono::milliseconds timed(100);
if (myLock.try_lock_until(std::chrono::steady_clock::now() + timed))
{
myQueue.push_back(i);
myLock.unlock();
}
else
{
std::chrono::milliseconds sleeptime(100);
std::this_thread::sleep_for(sleeptime);
}
5.2 std::recursive_timed_mutex :是待超时的递归独占互斥量,与上述5.1相比即可以对同一代码段多次加锁。
更多内容欢迎参见我的个人网站:http://www.huazhige.online/
|