• 按键公众号 :
按键精灵电脑版
立即下载

软件版本:2014.06
软件大小:22.9M
更新时间:2021-12-03

按键精灵安卓版
立即下载

软件版本:3.7.2
软件大小:46.2M
更新时间:2023-05-10

按键精灵iOS版
立即下载

软件版本:1.8.0
软件大小:29.2M
更新时间:2023-03-21

按键手机助手
立即下载

软件版本:3.8.0
软件大小:262M
更新时间:2023-05-30

快捷导航

登录 后使用快捷导航
没有帐号? 注册

发新话题 回复该主题

[技术交流] 【院刊】-【201503期】用互斥体解决多线程资源冲突问题 [复制链接]

1#

解决多线程资源冲突问题

本文按键学院提供技术支持



按键学院交流群(1群已满):376122403

零基础学按键精灵群(2群):372671254





故事就从一位童鞋的悲惨经历说起吧。
那是一个雷雨交加的夜晚
这位童鞋熬夜写了一个关于《赤月传说》交易功能的多线程多开脚本。
狂喜之余立马投身测试
测试的结果却让他的脸变成了屎色
他开了15个窗口,挂了半小时,就有10个窗口崩溃了。

他首先想到的是,会不会是电脑不给力,线程开多了导致的崩溃?
于是,他只开了5个窗口

啊~5个窗口崩了3个
这个问题困扰了他一个月,
后来才发现!
原来,游戏里规定,交易只能是一对一的
他没有在脚本中做处理
于是,启动脚本之后,所有的号都争着和交易号进行交易,
只有一个窗口抢到了和交易号交易的机会,其它的窗口没有抢到,就不断循环判断导致窗口崩溃
就像10个人争抢一个茅坑一样,1个人抢到了,其余9个人都掉坑里了……


怎么才能让他们好好排队上厕所呢?
很多童鞋可能会立马想到互斥体。
将交易的那段代码用互斥体保护起来,当一个线程在执行交易代码时,其它的线程就无法进行交易操作。
为了方便大家学习和使用,我们的06老湿提供了一段Api创建互斥体的代码范例~






API函数

要用到三个Api函数:
CreateMutex
WaitForSingleObject
ReleaseMutex

函数名称 CreateMutex
函数功能创建互斥体
参数参数1:指定一个SECURITY_ATTRIBUTES结构,或传递零值,表示使用不允许继承的默认描述符
参数2:如创建进程希望立即拥有互斥体,则设为TRUE。一个
互斥体同时只能由一个线程拥有。
参数3:指定
互斥体对象的名字。
返回值如执行成功,就返回互斥体对象的句柄;零表示出错。


函数名称 WaitForSingleObject
函数功能检测对象的信号状态,当函数的执行时间超过参数2设置的间隔时间,就返回无信号状态,
参数参数1:对象句柄
参数2:定时时间间隔
返回值WAIT_OBJECT_0 0x00000000 :核心对象已被激活
WAIT_TIMEOUT 0x00000102:等待超时
WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码



函数名称 ReleaseMutex
函数功能释放由线程拥有的一个互斥体的控制权
参数参数:指定一个互斥体的句柄。
返回值非零表示成功,零表示失败。



步骤

1调用Api函数:CreateMutex函数创建一个新的互斥体,并且将创建之后返回的互斥体句柄赋值给环境变量:交易



2交易代码执行之前,调用Api函数:WaitForSingleObject函数, 设置互斥体使用时长为30秒。(如果一个交易操作需要3分钟,则这里的使用时长设置为大于等于30分钟。)


当第一条线程执行到 WaitForSingleObject函数时,会获取30秒的互斥体使用时长,在这30秒时间内,只有第一条 线程可以执行被互斥体保护起来的代码段,其它的线程都在等待。



3交易代码执行之后,调用Api函数:ReleaseMutex函数, 释放互斥体使用权
当30秒时间过后,第一条线程会释放对互斥体的控制权,让给下一条线程使用。





代码
  1. Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Long , ByVal bInitialOwner As Long, ByVal lpName As String) As Long
  2. Declare Function ReleaseMutex Lib "kernel32" Alias "ReleaseMutex" (ByVal hMutex As Long)
  3. Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
  4. 'Declare Function CloseHandle lib "kernel32" (hdr as long) as Long

  5. Dimenv 交易
  6. 交易 = 创建互斥体()

  7. For 10
  8. BeginThread 游戏交易
  9. Next

  10. Sub 游戏交易()
  11. //绑定窗口
  12. //登录帐号
  13. //寻找npc
  14. Call 锁定(交易, 30000)
  15. //交易
  16. Call 解锁(交易)
  17. End Sub

  18. Function 创建互斥体()
  19. '/*随机生成互斥体名称
  20. Dim TempStr, i
  21. TempStr = "anjian_mutex_"
  22. For i = 0 To 12
  23. Randomize
  24. TempStr = TempStr & Chr((24 * Rnd) + 65)
  25. Next
  26. '*/
  27. 创建互斥体 = CreateMutex(0, true, TempStr)
  28. End Function

  29. Sub 关闭互斥体(hdr)
  30. Call CloseHandle(hdr)
  31. End Sub

  32. Function 锁定(Hdr, Max)
  33. 锁定 = WaitForSingleObject(Hdr, Max)
  34. End Function

  35. Function 解锁(Hdr)
  36. Call ReleaseMutex(Hdr)
  37. End Function

  38. /*
  39. Sub OnScriptExit()
  40. TracePrint "关闭互斥体"
  41. Call 关闭互斥体(交易)
  42. End Sub
  43. '*/
复制代码
注意1:
本例子中,在创建互斥体时,使用了随机产生互斥体的名称
随机名称是以 “[backcolor=rgb(247, 247, 247)]anjian_mutex_”开头并且加上12个随机字母
随机名称这样复杂是为了避免名称冲突,如果有一样的名称存在,那么当前的互斥体就会创建失败



注意2:
代码中还有一个CloseHandle函数,被注释掉了
因为,我们的主线程结束得比其它的十条线程快,所以当十条线程还在创建启动的过程中,主线程就已经结束,并且触发了脚本停止事件,执行了关闭互斥体的命令
这样会导致,刚创建的互斥体被关闭的情况
所以,如果主线程结束得比其他线程快,就不要使用关闭互斥体命令了
互斥体所占用的内存空间并不大,不关闭也不影响







那么,如果游戏规定, 登录帐号和交易 这两个操作都只能一个一个进行操作呢?
那么我们就需要设置两个互斥体:
登录互斥体 和 交易互斥体

代码:
  1. Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Long , ByVal bInitialOwner As Long, ByVal lpName As String) As Long
  2. Declare Function ReleaseMutex Lib "kernel32" Alias "ReleaseMutex" (ByVal hMutex As Long)
  3. Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
  4. 'Declare Function CloseHandle lib "kernel32" (hdr as long) as Long

  5. Dimenv 交易,登录
  6. 登录 = 创建互斥体()
  7. 交易 = 创建互斥体()

  8. For 10
  9. BeginThread 游戏交易
  10. Next

  11. Sub 游戏交易()

  12. //绑定窗口

  13. Call 锁定(登录, 30000)
  14. //登录帐号
  15. Call 解锁(登录)

  16. //寻找npc

  17. Call 锁定(交易, 30000)
  18. //交易
  19. Call 解锁(交易)
  20. End Sub

  21. Function 创建互斥体()
  22. '/*随机生成互斥体名称
  23. Dim TempStr, i
  24. TempStr = "anjian_mutex_"
  25. For i = 0 To 12
  26. Randomize
  27. TempStr = TempStr & Chr((24 * Rnd) + 65)
  28. Next
  29. '*/
  30. 创建互斥体 = CreateMutex(0, true, TempStr)
  31. End Function

  32. Sub 关闭互斥体(hdr)
  33. Call CloseHandle(hdr)
  34. End Sub

  35. Function 锁定(Hdr, Max)
  36. 锁定 = WaitForSingleObject(Hdr, Max)
  37. End Function

  38. Function 解锁(Hdr)
  39. Call ReleaseMutex(Hdr)
  40. End Function

  41. /*
  42. Sub OnScriptExit()
  43. TracePrint "关闭互斥体"
  44. Call 关闭互斥体(登录)
  45. Call 关闭互斥体(交易)
  46. End Sub
  47. '*/
复制代码






本文按键学院提供技术支持

零基础学按键精灵2015年开始招生!

全面系统回合制脚本教学




    已有4评分我要评分查看所有评分

    本主题由 超级版主 瑞祥幽冥狼 于 2023/6/4 23:35:24 执行 审核帖子 操作
    按键学院免费交流群:376122403

    按键学院招生计划
    按键学院系统教程
    2#

    太好了啊看看啊

    3#

    ddddddddddddddddddd

    承接各类脚本制作。接单QQ:493669373
    4#

    好 的 谢谢

    5#

    好好好

    6#

    1111111

    7#

    经济斤斤计较

    8#

    来学习的

    9#

    11111

    10#


    11#

    独家独家设计

    12#

    1111111111111

    13#

    学习学习学习

    14#

    ~~~~~~~~~~

    15#

    回复

    16#


    17#

    1111111111111111111111111111111111111111

    18#

    学习好好多少。

    [/color1]
    ❶:联系 QQ:1060790739
    ❷:交易方式:微信红包/QQ红包/支付宝
    ❸:营业时间:上午9:00-晚上02:00
    [/color2]
    ❹:层次方面:游戏指导/数据指导/安全防护/界面设计/数据分析
    ❺:技术方面:汇编/易语言/VBS脚本/内核编程/逆向/Delphi/Java/VC/
    ❻:官方网盘:http://binglang******.*****.com 暂时不公布
    [/color3]
    ❼:招聘求职:招收代理,共创双赢!
    ❽:温馨提示:本不私接外单,请不要随意加我好友!
    19#

    好东西。来学习

    20#

    是对方是否发顺丰

    脚本定制,请联系老冷QQ:1920712147
    发新话题 回复该主题