解决多线程资源冲突问题
本文由按键学院提供技术支持
按键学院交流群(1群已满):376122403
零基础学按键精灵群(2群):372671254
|
API函数
引用{:4_95:}
要用到三个Api函数:
CreateMutex
WaitForSingleObject
ReleaseMutex
| 函数名称 | CreateMutex |
| 函数功能 | 创建互斥体 |
| 参数 | 参数1:指定一个SECURITY_ATTRIBUTES结构,或传递零值,表示使用不允许继承的默认描述符 参数2:如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有。 参数3:指定互斥体对象的名字。 |
| 返回值 | 如执行成功,就返回互斥体对象的句柄;零表示出错。 |
| 函数名称 | WaitForSingleObject |
| 函数功能 | [size=13px]检测对象的信号状态,当函数的执行时间超过参数2设置的间隔时间,就返回无信号状态, |
| 参数 | 参数1:对象句柄 参数2:定时时间间隔 |
| 返回值 | WAIT_OBJECT_0 0x00000000 :核心对象已被激活 WAIT_TIMEOUT 0x00000102:等待超时 WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码 |
| 函数名称 | ReleaseMutex |
| 函数功能 | 释放由线程拥有的一个互斥体的控制权 |
| 参数 | 参数:指定一个互斥体的句柄。 |
| 返回值 | 非零表示成功,零表示失败。 |
步骤
1、调用Api函数:CreateMutex函数创建一个新的互斥体,并且将创建之后返回的互斥体句柄赋值给环境变量:交易 2、交易代码执行之前,调用Api函数:WaitForSingleObject函数, 设置互斥体使用时长为30秒。(如果一个交易操作需要3分钟,则这里的使用时长设置为大于等于3分钟。) 当第一条线程执行到 WaitForSingleObject函数时,会获取30秒的互斥体使用时长,在这30秒时间内,只有第一条 线程可以执行被互斥体保护起来的代码段,其它的线程都在等待。 3、交易代码执行之后,调用Api函数:ReleaseMutex函数, 释放互斥体使用权 当30秒时间过后,第一条线程会释放对互斥体的控制权,让给下一条线程使用。 |
代码
- Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Long , ByVal bInitialOwner As Long, ByVal lpName As String) As Long
- Declare Function ReleaseMutex Lib "kernel32" Alias "ReleaseMutex" (ByVal hMutex As Long)
- Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
- 'Declare Function CloseHandle lib "kernel32" (hdr as long) as Long
- Dimenv 交易
- 交易 = 创建互斥体()
- For 10
- BeginThread 游戏交易
- Next
- Sub 游戏交易()
- //绑定窗口
- //登录帐号
- //寻找npc
- Call 锁定(交易, 30000)
- //交易
- Call 解锁(交易)
- End Sub
- Function 创建互斥体()
- '/*随机生成互斥体名称
- Dim TempStr, i
- TempStr = "anjian_mutex_"
- For i = 0 To 12
- Randomize
- TempStr = TempStr & Chr((24 * Rnd) + 65)
- Next
- '*/
- 创建互斥体 = CreateMutex(0, true, TempStr)
- End Function
- Sub 关闭互斥体(hdr)
- Call CloseHandle(hdr)
- End Sub
- Function 锁定(Hdr, Max)
- 锁定 = WaitForSingleObject(Hdr, Max)
- End Function
- Function 解锁(Hdr)
- Call ReleaseMutex(Hdr)
- End Function
- /*
- Sub OnScriptExit()
- TracePrint "关闭互斥体"
- Call 关闭互斥体(交易)
- End Sub
- '*/
本例子中,在创建互斥体时,使用了随机产生互斥体的名称
随机名称是以 “anjian_mutex_”开头并且加上12个随机字母
随机名称这样复杂是为了避免名称冲突,如果有一样的名称存在,那么当前的互斥体就会创建失败
注意2:
代码中还有一个CloseHandle函数,被注释掉了
因为,我们的主线程结束得比其它的十条线程快,所以当十条线程还在创建启动的过程中,主线程就已经结束,并且触发了脚本停止事件,执行了关闭互斥体的命令
这样会导致,刚创建的互斥体被关闭的情况
所以,如果主线程结束得比其他线程快,就不要使用关闭互斥体命令了
互斥体所占用的内存空间并不大,不关闭也不影响
引用那么,如果游戏规定, 登录帐号和交易 这两个操作都只能一个一个进行操作呢?
那么我们就需要设置两个互斥体:登录互斥体 和 交易互斥体
代码:
- Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Long , ByVal bInitialOwner As Long, ByVal lpName As String) As Long
- Declare Function ReleaseMutex Lib "kernel32" Alias "ReleaseMutex" (ByVal hMutex As Long)
- Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
- 'Declare Function CloseHandle lib "kernel32" (hdr as long) as Long
- Dimenv 交易,登录
- 登录 = 创建互斥体()
- 交易 = 创建互斥体()
- For 10
- BeginThread 游戏交易
- Next
- Sub 游戏交易()
- //绑定窗口
- Call 锁定(登录, 30000)
- //登录帐号
- Call 解锁(登录)
- //寻找npc
- Call 锁定(交易, 30000)
- //交易
- Call 解锁(交易)
- End Sub
- Function 创建互斥体()
- '/*随机生成互斥体名称
- Dim TempStr, i
- TempStr = "anjian_mutex_"
- For i = 0 To 12
- Randomize
- TempStr = TempStr & Chr((24 * Rnd) + 65)
- Next
- '*/
- 创建互斥体 = CreateMutex(0, true, TempStr)
- End Function
- Sub 关闭互斥体(hdr)
- Call CloseHandle(hdr)
- End Sub
- Function 锁定(Hdr, Max)
- 锁定 = WaitForSingleObject(Hdr, Max)
- End Function
- Function 解锁(Hdr)
- Call ReleaseMutex(Hdr)
- End Function
- /*
- Sub OnScriptExit()
- TracePrint "关闭互斥体"
- <span style="font-size: 14.2857151031494px;">Call 关闭互斥体(登录)</span>
- Call 关闭互斥体(交易)
- End Sub
- '*/
{:5_141:}本文由按键学院提供技术支持{:5_141:}
零基础学按键精灵2015年开始招生! 全面系统回合制脚本教学
