C++ thread synchronization mutex Mutex

1. Mutually exclusive objects

        Mutexes are system kernel objects that enable threads to have absolute access to a resource . Mutex objects mainly include the number of uses, thread IDs, recursion counters , etc. The thread ID represents the thread that currently owns the mutex, and the recursion counter represents the number of times the thread has owned the mutex.

        1. When the thread ID of the mutex object is 0, it means that the mutex object is not owned by any thread. At this time, the system will issue a notification signal of the mutex object and wait for one of the other threads of the mutex object. will own the mutex object, and the thread ID of the mutex object is the thread ID of the thread that currently owns the mutex object.

        2. When the thread ID of the mutex object is not 0, it means that a thread currently owns the mutex object. The system does not issue notification signals for mutex objects. Other threads waiting for the mutex continue to wait until the thread that owns the mutex releases ownership of the mutex.

Second, create a mutex object

        The CreateMutex function creates a mutex object, returns the handle of the mutex object successfully, and returns NULL if it fails.

HANDLE WINAPI CreateMutex(
  __in LPSECURITY_ATTRIBUTES lpMutexAttributes,//Security attributes of mutex objects
  __in BOOL bInitialOwner,//The initial state of the mutex object; TRUE indicates that the thread ID of the mutex object is the thread ID of the current scheduling thread, the thread that currently creates the mutex object has its ownership, and the recursion counter of the mutex object is 1
  __in LPCTSTR lpName//The name of the mutex object, NULL means to create an anonymous mutex object
);

        When a thread has the ownership of the mutex object, it can monopolize the protected resources in the system; when the resource is no longer needed, it can call the ReleaseMutex function to release the ownership of the mutex object; each time the ReleaseMutex function is called, the recursion counter is decremented by 1; The mutex is not released until it is reduced to 0, and the mutex becomes the notification state.

BOOL WINAPI ReleaseMutex(
  __in          HANDLE hMutex
);

        Wait for the mutex object WaitForSingleObject function
DWORD WINAPI WaitForSingleObject(
  __in HANDLE hHandle,//Wait for the kernel object handle
  __in DWORD dwMilliseconds//waiting time, INFINITE means infinite wait
);

On failure return WAIT_FAILED;

3. Ticket sales system test questions

There are three slots for selling tickets; selling 100 tickets;

CMutex.h file

#ifndef _CMUTEX_H__
#define _CMUTEX_H__

class CMutex
{
public:
	CMutex();
	~CMutex();

	void StartThread();


	static DWORD __stdcall ThreadFun1(LPVOID lParam);//卖家1
	static DWORD __stdcall ThreadFun2(LPVOID lParam);//卖家2
	static DWORD __stdcall ThreadFun3(LPVOID lParam);//卖家3

private:
	HANDLE m_hThread1;
	HANDLE m_hThread2;
	HANDLE m_hThread3;

	HANDLE hMutex;//Mutex object

	static int nTickets;//The total number of tickets
};

#endif
#include "stdafx.h"
#include "CMutex.h"

int CMutex::nTickets = 100;

CMutex::CMutex()
{
	hMutex = CreateMutex(NULL, FALSE, L"mutex");
}

CMutex::~CMutex()
{
	if (NULL != hMutex)
	{
		CloseHandle(hMutex);
		hMutex = NULL;
	}

	if (NULL != m_hThread1)
	{
		CloseHandle(m_hThread1);
		m_hThread1 = NULL;
	}

	if (NULL != m_hThread2)
	{
		CloseHandle(m_hThread2);
		m_hThread2 = NULL;
	}

	if (NULL != m_hThread3)
	{
		CloseHandle(m_hThread3);
		m_hThread3 = NULL;
	}
}

DWORD __stdcall CMutex::ThreadFun1(LPVOID lParam)
{
	DWORD dRet = TRUE;
	CMutex * pThis = (CMutex*)lParam;
	while (1)
	{
		WaitForSingleObject(pThis->hMutex, INFINITE);
		if (pThis->nTickets < 1)
		{
			break;
		}
		cout<<"ThreadFun1 卖出票:"<<pThis->nTickets--<<endl;
		ReleaseMutex(pThis->hMutex);
	}
	return dRet;
}

DWORD __stdcall CMutex::ThreadFun2(LPVOID lParam)
{
	DWORD dRet = TRUE;
	CMutex * pThis = (CMutex*)lParam;
	while (1)
	{
		WaitForSingleObject(pThis->hMutex, INFINITE);
		if (pThis->nTickets < 1)
		{
			break;
		}
		cout<<"ThreadFun2 卖出票:"<<pThis->nTickets--<<endl;
		ReleaseMutex(pThis->hMutex);
	}
	return dRet;
}

DWORD __stdcall CMutex::ThreadFun3(LPVOID lParam)
{
	DWORD dRet = TRUE;
	CMutex * pThis = (CMutex*)lParam;
	while (1)
	{
		WaitForSingleObject(pThis->hMutex, INFINITE);
		if (pThis->nTickets < 1)
		{
			break;
		}
		cout<<"ThreadFun3 卖出票:"<<pThis->nTickets--<<endl;
		ReleaseMutex(pThis->hMutex);
	}
	return dRet;
}

void CMutex::StartThread()
{
	m_hThread1 = CreateThread(NULL, 0, &CMutex::ThreadFun1, this,  0, NULL);
	m_hThread2 = CreateThread(NULL, 0, &CMutex::ThreadFun2, this, 0, NULL);
	m_hThread3 = CreateThread(NULL, 0, &CMutex::ThreadFun3, this, 0, NULL);
}

main.cpp

// Mutex.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "CMutex.h"

int _tmain(int argc, _TCHAR* argv[])
{
	CMutex myMutex;
	myMutex.StartThread();

	Sleep(4000);
	system("pause");

	return 0;
}

result



If no mutex object is added, there will be the possibility of selling a ticket of 0;


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325772963&siteId=291194637