ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Windows编程-线程-线程同步2

2021-01-24 03:01:48  阅读:266  来源: 互联网

标签:HANDLE Windows 编程 WaitForSingleObject 信号量 线程 事件 NULL


Windows编程-线程-线程同步2

也是游戏防止多开的原理

事件

事件(Event)是在线程同步中最常使用的一种同步对象,事件包含一个使用计数,一个是用来表示自动重置/手动重置的布尔值,另一个是表示事件有没有触发的布尔值。

事件对象有两种状态:1、手动状态。2、自动状态

手动状态事件对象的激发态和非激发态是由我们来控制,自动状态和互斥体类似

事件也是一个内核对象

创建事件对象-CreateEvent

HANDLE CreateEventA(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL                 bManualReset,//如果此参数为TRUE,则该函数将创建一个手动重置的事件对象,该对象需要使用 ResetEvent函数将事件状态设置为非信号状态。如果此参数为FALSE,则该函数将创建一个自动重置事件对象,并且在释放单个等待线程之后,系统会自动将事件状态重置为非信号状态。
BOOL                 bInitialState,//如果为True就表示有信号状态,如果false就表示无信号状态,也就是一个初始状态
LPCSTR               lpName//事件的名字
);

例子:

HANDLE hEvent;
void Create_MyEvent()
{
hEvent = CreateEvent(NULL,FALSE,TRUE,L"Sna1lGo");
}

调用事件Event

WaitForsingleObject()

SetEvent()---将指定的事件对象设置为信号状态。

等待事件信号,然后用完之后重置事件

DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
for (int i = 0; i < 100; i++)
{
WaitForSingleObject(hEvent, -1);
Sum_Count++;
SetEvent(hEvent);
}
return 0;
}

事件对象没有拥有者的概念,谁都可以设置

利用事件来控制线程顺序

在创建线程的时候就先设置为无信号状态,然后有多少个线程就建立多少个事件,在自己想要的顺序中,依次设置信号,然后再唤醒下一个要执行的信号来操作。

//例子
#include<Windows.h>
#include<iostream>
HANDLE hEvent1;
HANDLE hEvent2;
HANDLE hEvent3;

LONG Sum_Count = 0;
void Create_MyEvent()
{
hEvent1 = CreateEvent(NULL,FALSE,TRUE,L"Sna1lGo");
hEvent2 = CreateEvent(NULL, FALSE, FALSE, L"Sna1lGo");
hEvent3 = CreateEvent(NULL, FALSE, FALSE, L"Sna1lGo");

}
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
WaitForSingleObject(hEvent1, -1);
printf("Hello ,this is Thread1\n");
SetEvent(hEvent2);
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
WaitForSingleObject(hEvent2, -1);
printf("Hello ,this is Thread2\n");
SetEvent(hEvent3);
return 0;
}
DWORD WINAPI ThreadProc3(LPVOID lpParameter)
{
WaitForSingleObject(hEvent3, -1);
printf("Hello ,this is Thread3\n");
return 0;
}

int main()
{
HANDLE hThread1 = CreateThread(NULL,NULL,ThreadProc1,NULL,0,NULL);
HANDLE hThread2 = CreateThread(NULL,NULL,ThreadProc2,NULL,0,NULL);
HANDLE hThread3 = CreateThread(NULL, NULL, ThreadProc3, NULL, 0, NULL);

WaitForSingleObject(hThread1, -1);
WaitForSingleObject(hThread2, -1);
WaitForSingleObject(hThread3, -1);
printf("Sum_Count=%ld\n", Sum_Count);

CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hThread3);
return 0;
}

信号量

信号量也没有拥有者的概念,但是它有数量

信号量有一个当前信号数,只要这个数不为0,信号量就处于激发态

当有线程调用WaitForSingleObject后,信号数减1,如果不为0的话,再有线程调用WaitForSingleObject会继续上一把锁。相反调用ReleaseSemaphoore会将信号量增1。如果信号量为0,当有线程调用WaitForSingleObject时,线程会被阻塞。

使用场景,多开数量检查

创建信号量-CreateSemaphore

HANDLE CreateSemaphoreW(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG                 lInitialCount,//信号量对象的初始计数
LONG                 lMaximumCount,//信号量对象的最大计数
LPCWSTR               lpName//信号量对象的名称
);

释放信号量-ReleaseSemaphore

将指定的信号量对象的计数增加指定的数量。

 

BOOL ReleaseSemaphore(
HANDLE hSemaphore,//信号量的句柄,由Create或者openSemaphore产生的
LONG   lReleaseCount,//信号量要增加的数量
LPLONG lpPreviousCount//指向变量的指针,以接收信号量的先前计数。如果不需要上一个计数,则此参数可以为NULL。
);

如果函数成功,则返回值为非零。

通过信号量来限制游戏多开

#include<Windows.h>
#include<iostream>
HANDLE hSemaphore;

int main()
{
hSemaphore = CreateSemaphore(NULL,0,3,L"SnailGo");
//创建信号量,最多三个,初始值为1个
BOOL Ret_Success = ReleaseSemaphore(hSemaphore,1,NULL);//调用一次添加一个信号量
if (Ret_Success == 0)
{
MessageBox(NULL, L"只能创建三个应用程序", L"创建失败", MB_OK);
exit(0);
}
system("pause");
return 0;
}

信号量总结

灵活应用信号量来限制多开

标签:HANDLE,Windows,编程,WaitForSingleObject,信号量,线程,事件,NULL
来源: https://www.cnblogs.com/Sna1lGo/p/14319878.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有