进程、线程同步互斥学习 —— 互斥器

本文介绍了C++中的互斥器Mutex,它用于实现线程间的同步互斥。Mutex在未被任何线程占用时为有信号状态,被占用时则变为无信号状态。创建Mutex可以通过CreateMutex或CreateMutexEx函数,并可指定是否立即拥有和命名。持有Mutex的线程可以使用ReleaseMutex释放。等待Mutex所有权可使用wait函数如WaitForSingleObject等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于互斥器,先看MSDN介绍:

Mutex Objects
A mutex object is a synchronization object whose state is set to signaled when it is not owned by any thread, and nonsignaled when it is owned. Only one thread at a time can own a mutex object, whose name comes from the fact that it is useful in coordinating mutually exclusive access to a shared resource. 

即:Mutex可以被某一个线程在某一时刻被单独拥有,Mutex从有信号转变成无信号。


初始化

A thread uses the CreateMutex orCreateMutexEx function to create a mutex object. The creating thread can request immediate ownership of the mutex object and can also specify a name for the mutex object. It can also create an unnamed mutex. 

HANDLE WINAPI CreateMutex(
  __in_opt  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  __in      BOOL bInitialOwner,
  __in_opt  LPCTSTR lpName
);
HANDLE WINAPI CreateMutexEx(
  __in_opt  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  __in_opt  LPCTSTR lpName,
  __in      DWORD dwFlags,
  __in      DWORD dwDesiredAccess
);

lpMutexAttributes SECURITY_ATTRIBUTES  安全属性。
bInitialOwner 如创建进程希望立即拥有互斥体,则设为TRUE,一个互斥体同时只能由一个线程拥有。
lpName String 指定互斥体对象的名字。

dwFlags  0或者CREATE_MUTEX_INITIAL_OWNER(0x00000001)

dwDesiredAccess  访问权限

当我们在做某俩进程互斥的时候,可用OpenMutex打开已存在的Mutex

HANDLE WINAPI OpenMutex(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  LPCTSTR lpName
);


wait操作

Any thread with a handle to a mutex object can use one of thewait functions to request ownership of the mutex object. 

我们可以用wait functions对Mutex进行等待操作

比如 SignalObjectAndWaitWaitForSingleObjectWaitForSingleObjectEx当某个线程得到Mutex时,此Mutex变为无信号状态。


signal操作

If the mutex object is owned by another thread, the wait function blocks the requesting thread until the owning thread releases the mutex object using theReleaseMutex function.

BOOL WINAPI ReleaseMutex(
  __in  HANDLE hMutex
);
即:释放MutexMutex变为有信号状态。


测试代码:

Mutex.h

#pragma once
#include <windows.h>

class ILock
{
public:
	virtual void lock() = 0;
	virtual void unlock() = 0;
};

class _CMutex : public ILock
{
public:
	_CMutex();
	~_CMutex();

	virtual void lock();
	virtual void unlock();
private:
	HANDLE m_hMutex;
};

class CLock
{
public:
	CLock(ILock&);
	~CLock();
private:
	ILock& m_lock;
};

Mutex.cpp

#include "stdafx.h"
#include "Mutex.h"
#include <assert.h>

_CMutex::_CMutex()
{
	m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
	assert(m_hMutex);
}

_CMutex::~_CMutex()
{
	::CloseHandle(m_hMutex);
}

void _CMutex::lock()
{
	WaitForSingleObject(m_hMutex, INFINITE);
}

void _CMutex::unlock()
{
	::ReleaseMutex(m_hMutex);
}


CLock::CLock(ILock& locker) : m_lock(locker)
{
	m_lock.lock();
}

CLock::~CLock()
{
	m_lock.unlock();
}
test.cpp
// Mutex_test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <process.h>
#include "Mutex.h"
#define THREADCOUNT 10
_CMutex g_mutex;
int nFood = 0;

unsigned int WINAPI EatThread(void *pParam)
{
	int i = (int)pParam;
	int nHasEaten = 0;
	while (true)
	{
		CLock lock(g_mutex);
		if (nFood > 0)
		{
			Sleep(100);
			std::cout << "消费者" << i << "进行消费,已经吃掉(" << ++nHasEaten << "),当前剩余食物" << --nFood << std::endl;
		}
		else
		{
			break;
		}
	}
	return 0;
}

unsigned int WINAPI ProductThread(void *pParam)
{
	int i = 0;
	while (i < 52)
	{
		std::cout << "生产者进行生产,当前剩余食物" << ++nFood << std::endl;
		i++;
	}
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hProductThread;
	HANDLE hEatThread[THREADCOUNT];

	hProductThread = (HANDLE)_beginthreadex(NULL, 0, &ProductThread, (void *)0, 0, 0);
	WaitForSingleObject(hProductThread, INFINITE);

	for (int i = 0; i < THREADCOUNT; i++)
	{
		hEatThread[i] = (HANDLE)_beginthreadex(NULL, 0, &EatThread, (void *)i, 0, 0);
	}
	WaitForMultipleObjects(THREADCOUNT, hEatThread, TRUE, INFINITE);

	::CloseHandle(hProductThread);
	for (int i = 0; i < THREADCOUNT; i++)
	{
		::CloseHandle(hEatThread[i]);
	}

	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值