线程锁
临界区实现之线程锁:
创建全局变量:
CRITICAL_SECTION cs;
初始化全局变量:
InitializeCriticalSection(&cs);
实现临界区:
EnterCriticalSection(&cs);
//使用临界资源
LeaveCriticalSection(&cs);
实例
#include <iostream>
#include<Windows.h>
//创建全局变量
CRITICAL_SECTION cs;
int a = 10;
void MyFirstThreadProc() {
EnterCriticalSection(&cs);
while (a > 0) {
a--;
printf("卖了一张,还有%d张票\n", a);
}
LeaveCriticalSection(&cs);
}
void MySecondThreadProc() {
EnterCriticalSection(&cs);
while (a > 0) {
a--;
printf("卖了一张,还有%d张票\n", a);
}
LeaveCriticalSection(&cs);
}
int main()
{
//初始化全局变量
InitializeCriticalSection(&cs);
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;
}
总结:
- 线程锁只能用于单个进程间的线程控制
- 线程锁情况中,如果一个线程意外终结,但是并没有释放令牌,那么就出现无限等待情况。
互斥体
临界区实现之互斥体:
跨进程的临界资源访问:
HANDLE CreateMutex()
创建一个互斥体(内核对象)
HANDLE g_hMutex=CreateMutex(NULL,FALSE,“xyz”)
“xyz”
:互斥体的名字
FALSE:FALSE
的话就是有信号(即可以直接使用);
TRUE 的话就是无信号(即不可以直接使用)(填TRUE的话,代表当前
这个互斥体属于当前这个进程)
//有两种情况是可以获取令牌 1.有信号 2.线程拥有者
扫描二维码关注公众号,回复:
12581103 查看本文章
获取令牌:
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);
}
//释放令牌
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);
}
//释放令牌
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(其实我也就加了一个getchar
):
#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返回值:
- 当前函数成功的话,那么返回值是一个互斥体的句柄
- 如果内核中同名互斥体已经存在了,那么CreateMutex这个函数也会返回一个句柄,返回值恰好就是原来按个互斥体的句柄。(但是此时GetlastError返回值是ERROR_ALREADY_EXISTS)
- 函数执行失败的话,返回值就是空
互斥体与线程锁的区别:
- 线程锁只能用于单个进程间的线程控制
- 互斥体可以设置等待超时,但线程锁不能
- 线程意外终结时,
Mutex
可以避免无限等待;线程锁情况中,如果一个线程意外终结,但是并没有释放令牌,那么就出现无限等待情况。 Mutex
效率没有线程锁高
事件
1.通知类型:
HANDLE CreatEvent(
LPSECURITY_ATTRIBUTES IpEventAttributes, //SD
BOOL bManualReset, //reset type
BOOL bInitialState, //initial state
LPCTSTR IpName //object name
);
bManualReset
是否是通知类型
bInitialState
是否有信号
有信号的话,就可以使用WaitForSingleObject
得到它;否则的话调用WaitForSingleObject
时会一直处于等待状态(FALSE
代表没有初始信号)
#include <iostream>
#include<Windows.h>
int a = 10;
HANDLE g_event;
void MyFirstThreadProc() {
SetEvent(g_event);//设置事件为已通知
WaitForSingleObject(g_event, INFINITE);
while (a > 0) {
a--;
printf("B进程的x线程卖了一张,还有%d张票\n", a);
}
}
void MySecondThreadProc() {
WaitForSingleObject(g_event, INFINITE);
while (a > 0) {
a--;
printf("B进程的y线程卖了一张,还有%d张票\n", a);
}
}
int main()
{
g_event = CreateEvent(NULL, FALSE, FALSE, NULL);
//第二个参数FALSE表示是否是通知类型,何为通知类型呢?也就是群发,A收到后,不会被改变它的状态;如果不是通知类型的话,那么A
//收到之后就会改变它的状态,然后B执行WaitForSingleObject不能成功。
//第三个参数表示是否有信号,TRUE为有信号,FALSE为无信号
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
);
// SetEvent(g_event);//设置事件为已通知
system("pause");
return 0;
}