MFC多线程互斥锁的使用

MFC多线程互斥锁的使用

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

第二部分:

1.在原有基础上(见上一篇文章MFC多线程的开启、暂停、继续和注销)添加一个EDIT控件和一个线程MyThread2。
MFC多线程互斥锁的使用_第1张图片
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,其他情况同理)。
MFC多线程互斥锁的使用_第2张图片
MFC多线程互斥锁的使用_第3张图片
7.互斥锁使用。上面修改中其实已经加入了互斥锁的必要说明,只需要把注销掉的代码复原即可实现。实际操作步骤如下:
①添加类变量声明

 CMutex Mutex;//用于互斥锁

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

CSingleLock singleLock(&Mutex);

③在线程中添加处理代码

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

8.修改后编译运行,可以看到使用互斥锁后,程序按预想的形式运行,EDIT1稳定的显示1,EDIT2稳定的显示-1。
MFC多线程互斥锁的使用_第4张图片
9.使用互斥锁后,当进入线程1时会先检查变量是否被调用,没有的话就上锁给自己用,待自己用完再解锁,如果变量已经被调用上锁了,那么久等待变量释放。这样在一个线程的运行周期内,其他线程就无法更改变量。

你可能感兴趣的:(MFC,MFC,多线程,互斥锁,C\C++)