MFC多线程互斥锁的使用

4 篇文章 0 订阅
该文介绍了如何在MFC环境下使用多线程和互斥锁。通过示例展示了如何开启、暂停、继续和注销线程,并通过CSingleLock实现线程间的同步,防止对共享资源的并发访问。在两个线程中,互斥锁确保了同一时间只有一个线程能访问和更新变量,保证了数据的一致性。
摘要由CSDN通过智能技术生成

MFC多线程互斥锁的使用
本例演示在MFC中使用多线程。第一部分实现多线程的开启、暂停、继续、注销(见上一篇文章MFC多线程的开启、暂停、继续和注销)。第二部分实现两个线程互斥锁的使用。
演示系统为Win10,平台为VS2017(MFC),主要使用类为CWinThread。

第二部分:
1.在原有基础上(见上一篇文章MFC多线程的开启、暂停、继续和注销)添加一个EDIT控件和一个线程MyThread2。

 

2.在ThreadTestDlg.h头文件中添加函数及变量声明:

static UINT MyThread2(LPVOID* pParam);//线程函数
CWinThread *Thread2;//线程2

3.在ThreadTestDlg.cpp实现文件上部中添加变量:

CMutex Mutex;//用于互斥锁

修改文件末尾线程1函数定义:

//线程1函数
UINT CThreadTestDlg::MyThread1(LPVOID* pParam)
{
	CThreadTestDlg *ap1 = (CThreadTestDlg *)pParam;//获取主类指针,在多线程类中使用主类变量需要使用指针ap1->
	CSingleLock singleLock(&Mutex);
	while(1)
	{
		if (ThreadKill)
		{
			DWORD dwExitCode;//指定线程的退出代码
			GetExitCodeThread(ap1->Thread1, &dwExitCode);//获取线程1的退出代码
			AfxEndThread(dwExitCode, TRUE);//退出线程
		}
		else
		{
			//singleLock.Lock();//没被调用就上锁自己用,已被调用就等着
			//if (singleLock.IsLocked()) 
			{
				n=1;
				strn.Format(_T("%d"), n);
				ap1->SetDlgItemText(IDC_EDIT1, strn);
				Sleep(30);
			}
			//singleLock.Unlock();//解锁
		}
	}
	return 0;
}

4.添加线程2函数定义:

UINT CThreadTestDlg::MyThread2(LPVOID* pParam)
{
	CThreadTestDlg *ap2 = (CThreadTestDlg *)pParam;//获取主类指针,在多线程类中使用主类变量需要使用指针ap1->
	CSingleLock singleLock(&Mutex);
	while (1)
	{
		if (ThreadKill)
		{
			DWORD dwExitCode;//指定线程的退出代码
			GetExitCodeThread(ap2->Thread2, &dwExitCode);//获取线程2的退出代码
			AfxEndThread(dwExitCode, TRUE);//退出线程
		}
		else
		{
			//singleLock.Lock();//没被调用就上锁自己用,已被调用就等着
			//if (singleLock.IsLocked())
			{
				n=-1;
				strn.Format(_T("%d"), n);
				ap2->SetDlgItemText(IDC_EDIT2, strn);
				Sleep(30);
			}
			//singleLock.Unlock();//解锁
		}
	}
	return 0;
}

5.修改按钮响应函数

void CThreadTestDlg::OnBnClickedButton1()
{
	n = 0;
	ThreadKill = FALSE;
	Thread1 = AfxBeginThread((AFX_THREADPROC)MyThread1, this);//启动线程
	Thread2 = AfxBeginThread((AFX_THREADPROC)MyThread2, this);//启动线程
}

void CThreadTestDlg::OnBnClickedButton2()
{
	Thread1->SuspendThread(); //暂停线程
	Thread2->SuspendThread(); //暂停线程
}

void CThreadTestDlg::OnBnClickedButton3()
{
	Thread1->ResumeThread(); //继续线程 
	Thread2->ResumeThread(); //继续线程 
}

void CThreadTestDlg::OnBnClickedButton4()
{
	ThreadKill = TRUE;//
	Thread1->ResumeThread(); //调用继续线程,排除线程处于暂停模式无法注销的情况。若线程处于工作状态,调用此函数无作用。
	Thread2->ResumeThread(); //调用继续线程,排除线程处于暂停模式无法注销的情况。若线程处于工作状态,调用此函数无作用。
}

6.编译运行。这是未加互斥锁的情况下,程序中,我们在线程1将n赋值为1并在EDIT1显示;在线程2中将同一个变量n赋值为-1并在EDIT2显示。理论上控件上应分别显示1和-1,但实际上,会出现同时显示1,或同时显示-1或显示-1和1的情况。这是由于线程间同时调用同一变量造成的(严格来讲并不是同时,而是比如线程1赋值为1后还没打印出来就被线程2赋值为-1了,所以造成最后打印出来都是-1,其他情况同理)。

 7.互斥锁使用。上面修改中其实已经加入了互斥锁的必要说明,只需要把注销掉的代码复原即可实现。实际操作步骤如下:
①添加类变量声明

 CMutex Mutex;//用于互斥锁

②在线程中定义互斥锁类变量

CSingleLock singleLock(&Mutex);

③在线程中添加处理代码

singleLock.Lock();//没被调用就上锁自己用,已被调用就等着
			if (singleLock.IsLocked()) 
			{
				//在此添加处理代码
			}
			singleLock.Unlock();//解锁

8.修改后编译运行,可以看到使用互斥锁后,程序按预想的形式运行,EDIT1稳定的显示1,EDIT2稳定的显示-1。

 

9.使用互斥锁后,当进入线程1时会先检查变量是否被调用,没有的话就上锁给自己用,待自己用完再解锁,如果变量已经被调用上锁了,那么久等待变量释放。这样在一个线程的运行周期内,其他线程就无法更改变量。


原文链接:https://blog.csdn.net/weixin_38179212/article/details/102102528

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值