IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Windows临界区 -> 正文阅读

[C++知识库]Windows临界区

一、windows临界区
Windows临界区:(使用前必须初始化)

//创建:
	CRITICAL_SECTION my_winsec;//创建windows中的临界区,类似与互斥量,使用前必须初始化

//初始化:(通常在类构造函数中初始化)
	InitializeCriticalSection(&my_winsec);//初始化临界区

//临界区使用:
	EnterCriticalSection(&my_winsec);//进入临界区(加锁)
	myQueue.push_back(i);
	LeaveCriticalSection(&my_winsec);//离开临界区(解锁)

二、windows临界区与C++ 11锁的异同:

  • 包含#include <windows.h>

  • Windows临界区,在同一个线程中是可以重复进入的,但是进入的次数与离开的次数必须相等
    C++互斥量则不允许同一个线程重复加锁,否则报异常。

  • 效果几乎可以等同于c++11的mutex,可以保护一个代码段。

关于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();
			//myLock.lock();
			myQueue.push_back(i);
			//myLock.unlock();
			myLock.unlock();
#endif // __WINDOWSJQ_	
			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 // __WINDOWSJQ_
		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 // __WINDOWSJQ_

	}

private:
	std::deque<int>myQueue;
	std::mutex myLock;

#ifdef __WINDOWSJQ_
	CRITICAL_SECTION my_winsec;//创建windows中的临界区,类似与互斥量,使用前必须初始化
#endif // __WINDOWSJQ_
};

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,可以根据其特点手写一个:

//自动释放Windows临界区,防止忘记解锁,即实现一个Windows的lock_guard();
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;//创建windows中的临界区
	
	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_mutexstd::recursive_timed_mutex:
5.1 std::timed_mutex

  • try_lock_for():等待一段时间,超时没拿到锁则停止阻塞,不再等待。
    例如:
	std::chrono::milliseconds timed(100);
	if (myLock.try_lock_for(timed))
	{
		//在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))
			{
				//在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/

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:14:26  更:2022-03-12 17:17:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:03:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码