【2021.01.03】互斥体

内核级临界资源怎么办?

  • 如果这个临界资源是内核级临界资源,例如是跨进程共享的物理页,或者是一个文件。
  • 这种情况下,不同进程同时访问内核级临界资源,这种情况下如何保证访问是安全的?

互斥体的使用

CreateMutex

创建一个互斥体。

HANDLE CreateMutexA(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  BOOL                  bInitialOwner,
  LPCSTR                lpName
);

Parameters

lpMutexAttributes

A pointer to a SECURITY_ATTRIBUTES structure. If this parameter is NULL, the handle cannot be inherited by child processes.

The lpSecurityDescriptor member of the structure specifies a security descriptor for the new mutex. If lpMutexAttributes is NULL, the mutex gets a default security descriptor. The ACLs in the default security descriptor for a mutex come from the primary or impersonation token of the creator. For more information, see Synchronization Object Security and Access Rights.

bInitialOwner

If this value is TRUE and the caller created the mutex, the calling thread obtains initial ownership of the mutex object. Otherwise, the calling thread does not obtain ownership of the mutex. To determine if the caller created the mutex, see the Return Values section.

lpName

The name of the mutex object. The name is limited to MAX_PATH characters. Name comparison is case sensitive.

If lpName matches the name of an existing named mutex object, this function requests the MUTEX_ALL_ACCESS access right. In this case, the bInitialOwner parameter is ignored because it has already been set by the creating process. If the lpMutexAttributes parameter is not NULL, it determines whether the handle can be inherited, but its security-descriptor member is ignored.

If lpName is NULL, the mutex object is created without a name.

If lpName matches the name of an existing event, semaphore, waitable timer, job, or file-mapping object, the function fails and the GetLastError function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same namespace.

The name can have a "Global" or "Local" prefix to explicitly create the object in the global or session namespace. The remainder of the name can contain any character except the backslash character (). For more information, see Kernel Object Namespaces. Fast user switching is implemented using Terminal Services sessions. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users.

The object can be created in a private namespace. For more information, see Object Namespaces.

A.cpp

#include <iostream>
#include <Windows.h>

int main(int argc, char* argv[])
{
	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, FALSE, (LPCWSTR)"XYZ");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);

	for (int i = 0; i < 10; i++)
	{
		Sleep(1000);
		std::cout << "进程A的X线程:" << i << "\n";
	}

	//释放令牌
	ReleaseMutex(g_hMutex);

	return 0;
}

B.cpp

#include <iostream>
#include <Windows.h>

int main(int argc, char* argv[])
{
	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, FALSE, (LPCWSTR)"XYZ");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);

	for (int i = 0; i < 10; i++)
	{
		Sleep(1000);
		std::cout << "进程B的Y线程:" << i << "\n";
	}

	//释放令牌
	ReleaseMutex(g_hMutex);

	return 0;
}

互斥体与线程锁的区别

  1. 线程锁只能用于单个进程的线程控制。
  2. 互斥体可以设定等待超时,但线程锁不能。
  3. 线程意外终结时,互斥体可以避免无限等待。
  4. 互斥体效率没有线程锁高。

互斥体实现防止程序多开

详情见MSDN文档,CreateMutex() 的返回值:

Return value

如果函数成功,则返回值是新创建的互斥对象的句柄。
如果函数失败,则返回值为NULL。要获取扩展错误信息,请调用GetLastError
如果互斥体是一个已经命名的互斥体,并且对象在此函数调用之前存在,则返回值是现有对象的句柄,GetLastError 函数返回 ERROR_ALREADY_EXISTS

#include <iostream>
#include <Windows.h>

int main(int argc, char* argv[])
{
	//创建一个互斥体
	HANDLE hMutex = CreateMutex(NULL, FALSE, (LPCWSTR)"OVER");

	DWORD dwRet = GetLastError();

	if (hMutex)
	{
		if (ERROR_ALREADY_EXISTS == dwRet)
		{
			std::cout << "禁止多开, 按任意键退出!\n";

			CloseHandle(hMutex);

			std::cin.get();

			return 0;
		}
	}
	else
	{
		std::cout << "创建互斥体失败, 按任意键退出!\n";

		CloseHandle(hMutex);

		std::cin.get();

		return 0;
	}

	while (1)
	{
		Sleep(1000);

		std::cout << "执行中...\n" ;
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值