[MFC]同步对象——CCriticalSection临界区,CSemaphore信号量

[MFC]同步对象——CCriticalSection临界区,CSemaphore信号量实例——CCriticalSection临界区临界区是保证在某一个时间只有一个线程可以访问数据的方法。使用它的过程中,需要给每个线程提供一个共享的临界区对象,无论哪个线程占有临界区对象,都可以访问受到保护的数据,这时候其他的线程需要等待,直至该线程释放临界区对象为止,临界区被释放后,另外的线程可以强占这个临界区,以便访问共享的数据。临界区对应的一个CCriticalSection对象,

大家好,又见面了,我是你们的朋友全栈君。

实例——CCriticalSection临界区

临界区是保证在某一个时间只有一个线程可以访问数据的方法。使用它的过程中,需要给每个线程提供一个共享的临界区对象,无论哪个线程占有临界区对象,都可以访问受到保护的数据,这时候其他的线程需要等待,直至该线程释放临界区对象为止,临界区被释放后,另外的线程可以强占这个临界区,以便访问共享的数据。

临界区对应的一个CCriticalSection对象,当线程需要访问保护数据时,调用临界区对象的Lock()成员函数;当对保护数据的操作完成之后,调用临界区对象的Unlock()成员函数释放临界区对象的拥有权,以使另一个线程可以夺取临界区对象并访问受保护的数据。

头文件关键代码:
// MFCCriticalSectionDlg.h : 头文件 
#pragma once
#define  WM_MSG WM_USER+1
typedef struct THREAD_PARAM
{
	HWND hWnd;
	int nData;
	CCriticalSection* pCriticalSection;
}_THREAD_PARAM;
UINT ThreadFun1(LPVOID pParam);
UINT ThreadFun2(LPVOID pParam);
cpp文件关键代码:
//MFCCriticalSectionDlg.cpp : 实现文件
CMFCCriticalSectionDlg::CMFCCriticalSectionDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CMFCCriticalSectionDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	//成员变量
	//	CWinThread* pThread1;
	// 	CWinThread* pThread2;
	// 	THREAD_PARAM mThreadParam;
	pThread1=NULL;
	pThread2=NULL;
	mThreadParam.hWnd=NULL;
	mThreadParam.nData=0;
	mThreadParam.pCriticalSection=new CCriticalSection;
	//存取或者释放一个CCriticalSection对象,要先建立一个CSiingleLock对象,并调用它的Lock和UnLock成员函数。如果CCriticalSection对象是独占使用的,需要调用它的UnLock成员函数以释放对它的占用。或者使用其自身的成员函数Lock()和UnLock()来占有或释放临界区的拥有权。 
}
CMFCCriticalSectionDlg::~CMFCCriticalSectionDlg()
{
	if (pThread1)
	{
		WaitForSingleObject(pThread1->m_hThread,INFINITE);
		delete pThread1;
		pThread1=NULL;
	}
	if (pThread2)
	{
		WaitForSingleObject(pThread2->m_hThread,INFINITE);
		delete pThread2;
		pThread2=NULL;
	}
	if (mThreadParam.pCriticalSection)
	{
		delete mThreadParam.pCriticalSection;
		mThreadParam.pCriticalSection=NULL;
	}
}
//WM_MSG消息函数
LRESULT CMFCCriticalSectionDlg::OnMsgFun(WPARAM wParam,LPARAM lParam)
{
	SetDlgItemInt(IDC_EDIT_DATA,mThreadParam.nData);
	return 0;
}
//启动线程按钮事件
void CMFCCriticalSectionDlg::OnBnClickedButtonStart()
{ 
	if (pThread1)
	{
		DWORD exitCode=0;
		if (::GetExitCodeThread(pThread1->m_hThread,&exitCode))
		{
			if (exitCode == STILL_ACTIVE)
			{
				AfxMessageBox(_T("线程1已经启动。"));
				return;
			}
			else
			{
				delete pThread1;
				pThread1=NULL;
			}
		}
	}
	if (pThread2)
	{
		DWORD exitCode=0;
		if (::GetExitCodeThread(pThread2->m_hThread,&exitCode))
		{
			if (exitCode == STILL_ACTIVE)
			{
				AfxMessageBox(_T("线程2已经启动。"));
				return;
			}
			else
			{
				delete pThread2;
				pThread2=NULL;
			}
		}
	}
	mThreadParam.hWnd=m_hWnd;
	pThread1=AfxBeginThread(ThreadFun1,&mThreadParam,THREAD_PRIORITY_ABOVE_NORMAL,0,CREATE_SUSPENDED); 
	pThread2=AfxBeginThread(ThreadFun2,&mThreadParam,THREAD_PRIORITY_ABOVE_NORMAL,0,CREATE_SUSPENDED);  
	pThread1->m_bAutoDelete=FALSE;
	pThread2->m_bAutoDelete=FALSE;
	pThread1->ResumeThread();
	pThread2->ResumeThread();
}
//线程函数1
UINT ThreadFun1(LPVOID pParam)
{
	THREAD_PARAM* pThreadParam=(THREAD_PARAM*)pParam;
	pThreadParam->pCriticalSection->Lock();
	for (int i=0;i<10;i++)
	{
		pThreadParam->nData++;
		::PostMessage(pThreadParam->hWnd,WM_MSG,0,0);
		Sleep(200);
	}
	pThreadParam->pCriticalSection->Unlock();
	return 0;
}
//线程函数2
UINT ThreadFun2(LPVOID pParam)
{
	THREAD_PARAM* pThreadParam=(THREAD_PARAM*)pParam;
	pThreadParam->pCriticalSection->Lock();
	for (int i=0;i<10;i++)
	{
		pThreadParam->nData--;
		::PostMessage(pThreadParam->hWnd,WM_MSG,0,0);
		Sleep(200);
	}
	pThreadParam->pCriticalSection->Unlock();
	return 0;
}

结果图:
[MFC]同步对象——CCriticalSection临界区,CSemaphore信号量

实例——CSemaphore信号量

信号量的用法和互斥量的用法很相似,不同的是它可以同一时刻允许多个线程访问同一个资源,创建一个信号量需要用CSemaphore类声明一个对象,一旦创建了一个信号量对象,就可以用它来对资源的访问计数。要实现计数,先创建一个CSingleLockCMultiLock对象,然后用该对象的Lock()函数减少一个信号量的计数值,Unlock()反之。

头文件关键代码:
// MFCSemaphoreDlg.h : 头文件 
#pragma once
#define  WM_MSG WM_USER+1
typedef struct THREAD_PARAM
{
	HWND hWnd;
	int nData;
	CSemaphore* pSemaphore;
}_THREAD_PARAM;
UINT ThreadFun(LPVOID pParam);

cpp文件关键代码:
// MFCSemaphoreDlg.cpp : 实现文件
CMFCSemaphoreDlg::CMFCSemaphoreDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CMFCSemaphoreDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	//成员变量
	//THREAD_PARAM mThreadParam;
	//CObArray mThreadArray;
	mThreadParam.nData=0;
	mThreadParam.pSemaphore=new CSemaphore(2,2);//连续单击多次只会增加20次,若:CSemaphore(1,2)连续单击多次增加10次
	/*
	CSemaphore( LONG lInitialCount = 1,
	LONG lMaxCount = 1,
	LPCTSTR pstrName= NULL,
	LPSECURITY_ATTRIBUTES lpsaAttributes = NULL);
	参数: lInitialCount 信号的初始使用计数。必须是大于或等于0,并且小于或等于lMaxCount。  
	           lMaxCount 信号的使用计数的最大值。必须大于0。  
	           pstrName 信号的名字。 
	           lpsaAttributes 此信号对象的安全标志。有关这个结构的详细描述,参见“Win32 SDK程序员参考”中的SECURITY_ATTRIBUTES。  
	说明: 此成员函数用来构造一个有名字或没有名字的CSemaphore对象。要访问或释放一个CSemaphore对象,可以创建一个CMultiLock或CSingleLock对象,并调用它们的Lock和Unlock函数。
	*/
}
CMFCSemaphoreDlg::~CMFCSemaphoreDlg()
{
	int count=mThreadArray.GetCount();
	for (int i=0;i<mThreadArray.GetCount();i++)
	{
		CWinThread* pThread=(CWinThread*)mThreadArray.GetAt(i);
		if (pThread)
		{
			::WaitForSingleObject(pThread->m_hThread,INFINITE);//等待线程结束
			delete pThread;
			pThread=NULL;
		}
	}
	mThreadArray.RemoveAll();
	if (mThreadParam.pSemaphore)
	{
		delete mThreadParam.pSemaphore;
		mThreadParam.pSemaphore=NULL;
	}
}
//WM_MSG消息函数
LRESULT CMFCSemaphoreDlg::OnMsgFun(WPARAM wParam,LPARAM lParam)
{
	SetDlgItemInt(IDC_EDIT_DATA,mThreadParam.nData);
	return 0;
}
//启动线程按钮事件
void CMFCSemaphoreDlg::OnBnClickedButtonStart()
{ 
	mThreadParam.hWnd=m_hWnd;
	CWinThread* pThread=AfxBeginThread(ThreadFun,&mThreadParam,THREAD_PRIORITY_ABOVE_NORMAL,0,CREATE_SUSPENDED);//启动线程,初始为挂起状态  pthread 0x006ecd68 pro 0x01253700
	mThreadArray.Add((CObject*)pThread);//将线程指针添加到数组中
	pThread->m_bAutoDelete=FALSE;//线程结束时不自动删除 mdata 0x006e6860
	pThread->ResumeThread();//恢复线程运行
}
//线程函数
UINT ThreadFun(LPVOID pParam)
{
	THREAD_PARAM* pThreadParam=(THREAD_PARAM*)pParam;	 
	CSingleLock singleLock(pThreadParam->pSemaphore);
	singleLock.Lock(0);//锁定
	if (singleLock.IsLocked())
	{
		for (int i=0;i<10;i++)
		{
			pThreadParam->nData++;
			PostMessage(pThreadParam->hWnd,WM_MSG,0,0);
			Sleep(100);
		}
	} 
	singleLock.Unlock();//解锁
	return 0;
}

结果图:
[MFC]同步对象——CCriticalSection临界区,CSemaphore信号量
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/162045.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • LDA Effect Size分析 LEfSe详解

    LDA Effect Size分析 LEfSe详解LDAEffectSize分析LEfSe详解LEfSe的作用LEfSe的原理LEfSe的作用在介绍LEfSe的作用前,我们先解释一个概念——biomarker,维基百科给出的定义是Abio-marker,orbiologicalmarkerisameasurableindicatorofsomebiologicalstateorcondition.Biomarkersareoftenmeasuredandevaluatedtoexaminenorma

    2022年5月2日
    51
  • 手机浏览器唤起微信实现分享

    手机浏览器唤起微信实现分享

    2021年10月28日
    36
  • 软件测试面试问题及答案_中软国际测试面试笔试题

    软件测试面试问题及答案_中软国际测试面试笔试题文章目录软测面试题附答案<二>二、接口面试题1、你们公司的接口测试流程是怎样的?2、接口测试里面如何分析一个bug是前端还是后端的?3、Jmeter参数化的方式有哪几种可以实现4、在接口测试中关联是什么含义?一般什么场景需要用到,postman中是怎样用的?5、常用的性能指标名称与具体含义?6、没有接口和文档怎么进行工作?三、自动化面试题1、Selenium中有哪几种元素定位方式?2、隐式等待与显式等待有什么不同?3、自动化测试里面遇到验证码,一般怎么处理比较好?四、安全1、什么是SQL注入攻击

    2022年9月29日
    3
  • Spring Batch事务处理

    Spring Batch事务处理之前一直对SpringBatch的使用有些迷糊,尤其是事务这块,经常出些莫名其妙的问题,仔细了解了一下,做个小总结

    2022年5月13日
    35
  • 学生个人网页制作html_学生管理html页面

    学生个人网页制作html_学生管理html页面<!DOCTYPEhtml><htmllang=”en”><head><metacharset=”UTF-8″><title>Title</title><styletype=”text/css”>*{margin:0;…

    2025年10月26日
    2
  • maven 菜鸟安装教程「建议收藏」

    maven 菜鸟安装教程「建议收藏」文章目录Maven是什么Maven安装Maven设置环境变量配置总结Maven是什么maven是一套用来管理jar包的软件,在Maven项目里面有个pom.xml文件,这是这个maven的配置文件,里面可以导入各种你需要导入的依赖,然后maven就能找到相关的依赖在你的本地库,本地库没有就在中央仓库下载,然后保存到本地库,十分方便Maven安装网上找到资源,一般是压缩包,解压即用Maven设置软件–>conf–>setting.xml进入setting.xm

    2025年10月8日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号