上节课的内容仅仅能够保证同一个进程中的多个线程安全,但无法保证内核级(可以跨进程共享)临界资源的安全问题
要把临界资源放到内核里,互斥体就是能够放在内核中的临界资源
A进程中的某个线程,要访问内核级的临界资源时,首先要访问0环的互斥体,如果能访问就可以对临界资源进行操作,
此时另外的进程B中的线程要访问内核级的临界资源,也要取获取0环的互斥体,这个时候如果令牌时被占用,那么就无法对临界资源进行操作
cHANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针 BOOL bInitialOwner, // 初始化互斥体的所有者,一创建出来互斥体就能用,也就是有信号,就填FALSE,没有信号就填TRUE LPCTSTR lpName // 指向互斥体的指针 );
c# include <windows.h> int main() { //创建一个互斥体 HANDLE g_hMutex = CreateMutex(NULL,FALSE,"XYZ"); //获取令牌,以后信号,线程的拥有者 WaitForSingleObject(g_hMutex,INFINITE); //操作资源 for(int i = 0; i < 10; i++) { Sleep(1000); printf("A进程的X线程: %d\r\n",i); } //释放令牌 ReleaseMutex(g_hMutex); return 0; }
线程锁只能用于单个进程间的线程控制
互斥体可以设定等待超时,但线程锁不能
线程意外终结时,Mutex可以避免无限等待
Mutex效率没有线程锁高
互斥体MSDN返回值:
如果函数成功.则返回互斥体的句柄.如果调用此函数.发现名字已经有了.表示这个函数在之前已经调用过了.所以则会返回 ERROR_ALREADY_EXISTS的宏. 这个宏的意思就是已经存在.
如果函数失败.则返回NULL. 返回的宏必须调用 GetlastError获取.
c# include <Windows.h> //创建临界区结构 int main(int argc, char *argv[]) { //初始化临界区全局原子变量 HANDLE MutexHandle = CreateMutex(NULL, FALSE, TEXT("AAA")); //创建互斥体. 信号量为0. 有信号的状态.wait可以等待 DWORD ErrorCode = 0; ErrorCode = GetLastError(); if (ERROR_ALREADY_EXISTS == ErrorCode) //==时,说明已经不是第一次启动了 { printf("对不起,程序已经启动一份了.这份即将关闭\r\n"); CloseHandle(MutexHandle); system("pause"); } if (NULL == MutexHandle) { return 0; //表示句柄获取失败 } for (size_t i = 0; i < 10; i++) { Sleep(1000); printf("当前程序运行中. EIP 位置 等于 %d \r\n", i); } system("pause"); return 0; }
本文作者:Na1r
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!