互斥体摘要:
看过我上一篇文章的人应该已经理解了临界区,那既然已经明白临界区了那互斥体就很好理解了,互斥体其实和临界区一样,唯一的区别就是,临界区是为了解决多个线程同时访问同一资源产生的问题,而互斥体是为了解决多个进程访问同一资源产生的问题。
逻辑图例
可以很明显的看到,进程A中X线程和进程B中Y线程,要访问同一个内核层的临界资源,如果不懂临界是什么并且不清楚会产生什么安全问题,建议去看看我上一章文章,不然断层太大,看不懂,那为了解决多个进程要访问同一个临界资源而产生的安全问题,就此互斥体诞生。
秒懂图例:
跟上一章的进程锁如出一辙,一样的原理。
我们直接上代码,从代码层面解析互斥体。
进程1
//创建一个互斥体
HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");
//获取令牌
WaitForSingleObject(g_hMutex, INFINITE);
//释放令牌
ReleaseMutex(g_hMutex);
代码示例:
#include <iostream>
#include<Windows.h>
int a = 10;
void MyFirstThreadProc() {
//创建一个互斥体
HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");
//获取令牌
WaitForSingleObject(g_hMutex, INFINITE);
while (a > 0) {
a--;
printf("A进程的x线程卖了一张,还有%d张票\n", a);
}
getchar();
//释放令牌
ReleaseMutex(g_hMutex);
}
void MySecondThreadProc() {
//创建一个互斥体
HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");
//获取令牌
WaitForSingleObject(g_hMutex, INFINITE);
while (a > 0) {
a--;
printf("B进程的y线程卖了一张,还有%d张票\n", a);
}
getchar();
//释放令牌
ReleaseMutex(g_hMutex);
}
int main()
{
HANDLE aThreadProc[2];
aThreadProc[1] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
NULL,
0,
NULL
);
aThreadProc[2] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)MySecondThreadProc,
NULL,
0,
NULL
);
system("pause");
return 0;
}
进程2
#include <iostream>
#include<Windows.h>
int a = 10;
void MyFirstThreadProc() {
//创建一个互斥体
HANDLE g_hMutex = CreateMutex(NULL, FALSE, "xy");
//获取令牌
WaitForSingleObject(g_hMutex, INFINITE);
while (a > 0) {
a--;
printf("B进程的x线程卖了一张,还有%d张票\n", a);
}
//释放令牌
ReleaseMutex(g_hMutex);
}
void MySecondThreadProc() {
//创建一个互斥体
HANDLE g_hMutex = CreateMutex(NULL, FALSE, "xy");
//获取令牌
WaitForSingleObject(g_hMutex, INFINITE);
while (a > 0) {
a--;
printf("B进程的y线程卖了一张,还有%d张票\n", a);
}
//释放令牌
ReleaseMutex(g_hMutex);
}
int main()
{
HANDLE aThreadProc[2];
aThreadProc[1] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
NULL,
0,
NULL
);
aThreadProc[2] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)MySecondThreadProc,
NULL,
0,
NULL
);
system("pause");
return 0;
}
互斥体1进程执行完了,但是互斥体1还没释放锁,因此互斥体2是不可能执行的,接下来我在互斥体1中按下回车键
CreateMutex返回值:
1、返回值是一个互斥体的句柄
2、如果内核中同名互斥体已经存在了,那么CreateMutex这个函数也会返回一个句柄,返回值恰好就是原来按个互斥体的句柄。
3、函数执行失败的话,返回值就是空。