【玩转cocos2d-x之二十二】多线程和同步02-售票

前端之家收集整理的这篇文章主要介绍了【玩转cocos2d-x之二十二】多线程和同步02-售票前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

原创作品,转载请标明:@H_301_6@http://www.jb51.cc/article/p-ntfjuwne-ep.html
@H_301_6@


@H_301_6@

pthread有很多不同应用,官网都有相应的API解释和Sample,这里不再重复,本文主要介绍一个cocos2d-x多线程和同步示例。@H_301_6@


@H_301_6@

1.售票@H_301_6@

孙鑫老师的C++和Java多线程售票一直让我念念不忘,好吧,这里用cocos2d-x和pthread实现一个吧。总共有100张火车票,有2个售票点A和B再售票,当票卖完了就结束了。我们知道当程序一开始进程就会创建一个主线程,所以可以在主线程基础上再创建2个线程A和B,再线程A和B中分别售票,当票数为0的时候,结束线程A和B。@H_301_6@


2.多线程售票@H_301_6@

@H_301_6@

  1. //TestLayer.h@H_301_6@@H_301_6@@H_301_6@
  2. class@H_301_6@CTestLayer:@H_301_6@@H_301_6@
  3. public@H_301_6@CCLayer@H_301_6@@H_301_6@
  4. {@H_301_6@
  5. public@H_301_6@:@H_301_6@@H_301_6@
  6. CTestLayer(void@H_301_6@);@H_301_6@@H_301_6@
  7. ~CTestLayer(void@H_301_6@);@H_301_6@@H_301_6@
  8. @H_301_6@
  9. CREATE_FUNC(CTestLayer);@H_301_6@
  10. virtual@H_301_6@@H_301_6@bool@H_301_6@init();@H_301_6@@H_301_6@
  11. @H_301_6@
  12. pthread_tsellA_pid,sellB_pid;//线程id@H_301_6@@H_301_6@@H_301_6@
  13. static@H_301_6@@H_301_6@int@H_301_6@tickets;@H_301_6@//票数@H_301_6@@H_301_6@@H_301_6@
  14. static@H_301_6@@H_301_6@void@H_301_6@*threadA(@H_301_6@void@H_301_6@*p);@H_301_6@//线程A回调@H_301_6@@H_301_6@@H_301_6@
  15. void@H_301_6@*threadB(@H_301_6@//线程B回调@H_301_6@@H_301_6@@H_301_6@
  16. };@H_301_6@
  17. //TestLayer.cpp@H_301_6@@H_301_6@@H_301_6@
  18. #include"TestLayer.h"@H_301_6@@H_301_6@@H_301_6@
  19. int@H_301_6@CTestLayer::tickets=100;@H_301_6@//初始化票数100@H_301_6@@H_301_6@@H_301_6@
  20. CTestLayer::CTestLayer(void@H_301_6@)@H_301_6@@H_301_6@
  21. {@H_301_6@
  22. }@H_301_6@
  23. CTestLayer::~CTestLayer(void@H_301_6@)@H_301_6@@H_301_6@
  24. }@H_301_6@
  25. bool@H_301_6@CTestLayer::init()@H_301_6@@H_301_6@
  26. bool@H_301_6@bRet=@H_301_6@false@H_301_6@;@H_301_6@@H_301_6@
  27. do@H_301_6@@H_301_6@@H_301_6@
  28. CC_BREAK_IF(!CCLayer::init());@H_301_6@
  29. pthread_create(&sellA_pid,NULL,threadA,0);//创建线程A@H_301_6@@H_301_6@@H_301_6@
  30. pthread_create(&sellB_pid,threadB,0); background-color:inherit">//创建线程B@H_301_6@@H_301_6@@H_301_6@
  31. bRet=true@H_301_6@;@H_301_6@@H_301_6@
  32. }while@H_301_6@(0);@H_301_6@@H_301_6@
  33. return@H_301_6@bRet;@H_301_6@@H_301_6@
  34. void@H_301_6@*CTestLayer::threadA(@H_301_6@void@H_301_6@*p)@H_301_6@@H_301_6@
  35. while@H_301_6@(@H_301_6@true@H_301_6@)@H_301_6@@H_301_6@
  36. if@H_301_6@(tickets>0)@H_301_6@@H_301_6@
  37. CCLog("ASell%d"@H_301_6@,tickets--);@H_301_6@//输出售票,每次减1@H_301_6@@H_301_6@@H_301_6@
  38. else@H_301_6@{@H_301_6@@H_301_6@
  39. break@H_301_6@;@H_301_6@@H_301_6@
  40. return@H_301_6@NULL;@H_301_6@@H_301_6@
  41. void@H_301_6@*CTestLayer::threadB(@H_301_6@void@H_301_6@*p)@H_301_6@@H_301_6@
  42. true@H_301_6@)@H_301_6@@H_301_6@
  43. if@H_301_6@(tickets>0)@H_301_6@@H_301_6@
  44. CCLog("BSell%d"@H_301_6@,tickets--);@H_301_6@@H_301_6@
  45. else@H_301_6@@H_301_6@@H_301_6@
  46. }@H_301_6@
代码很简单,不多说了。我们来看一下输出,会发现有很多不可思议的现象出现,因为每个人每次运行的结果都不一样,所以这里不贴结果了,不可思议的现象可能有:@H_301_6@ @H_301_6@

(1)同一张票卖了2次。@H_301_6@

(2)后面的票比前面的票先卖出去。@H_301_6@

(3)第0张票竟然也可以卖。(这算站票么。。。)@H_301_6@

原因不多解释了,时间片的问题,不明白的Google之。如果你觉得不会有这么巧,那么在打印结果前加上这么一句:@H_301_6@

@H_301_6@

copy
    Sleep(100);@H_301_6@@H_301_6@
人为干扰线程的运行,增大出错几率。结果可能会是这样:@H_301_6@ @H_301_6@

@H_301_6@

copy
    ASell36@H_301_6@@H_301_6@
  1. BSell36//卖2次了@H_301_6@@H_301_6@@H_301_6@
  2. ASell35@H_301_6@
  3. BSell34@H_301_6@
  4. ASell33@H_301_6@
  5. BSell32@H_301_6@
  6. ASell30//提早卖了@H_301_6@@H_301_6@@H_301_6@
  7. BSell31@H_301_6@
  8. BSell28@H_301_6@
  9. ASell29@H_301_6@
  10. ASell27@H_301_6@
  11. BSell26@H_301_6@
  12. ASell25@H_301_6@
  13. BSell24@H_301_6@
  14. ASell23@H_301_6@
  15. BSell22@H_301_6@
  16. ASell21@H_301_6@
  17. BSell20@H_301_6@
  18. ASell19@H_301_6@
  19. BSell18@H_301_6@
  20. ASell17@H_301_6@
  21. BSell16@H_301_6@
  22. ASell15@H_301_6@
  23. BSell14@H_301_6@
  24. ASell13@H_301_6@
  25. BSell12@H_301_6@
  26. ASell11@H_301_6@
  27. BSell10@H_301_6@
  28. ASell9@H_301_6@
  29. BSell8@H_301_6@
  30. ASell7@H_301_6@
  31. BSell6@H_301_6@
  32. ASell5@H_301_6@
  33. BSell4@H_301_6@
  34. ASell3@H_301_6@
  35. BSell2@H_301_6@
  36. ASell1@H_301_6@
  37. BSell0//站票。。。@H_301_6@@H_301_6@@H_301_6@

3.利用互斥对象同步数据@H_301_6@

这个问题主要是因为一个线程执行到一半的时候,时间片的切换导致另一个线程修改了同一个数据,当再次切换会原来线程并继续往下运行的时候,数据由于被修改了导致结果出错。所以我们要做的就是保证这个线程完全执行完,所以对线程加锁是个不错的注意,互斥对象mutex就是这个锁。@H_301_6@

3.1.初始化@H_301_6@

在cpp外分配空间:@H_301_6@

@H_301_6@

copy
    pthread_mutex_tCTestLayer::mutex;@H_301_6@//mutex是静态成员变量@H_301_6@@H_301_6@@H_301_6@

在init中初始化,动态初始化:@H_301_6@

@H_301_6@

copy
    pthread_mutex_init(&mutex,NULL);@H_301_6@@H_301_6@

3.2.加锁和解锁@H_301_6@

以线程A为例:@H_301_6@

@H_301_6@

copy
    pthread_mutex_lock(&mutex);//加锁@H_301_6@@H_301_6@@H_301_6@
  1. Sleep(100);@H_301_6@
  2. 301_6@@H_301_6@
  3. pthread_mutex_unlock(&mutex);//解锁@H_301_6@@H_301_6@@H_301_6@
  4. else@H_301_6@{@H_301_6@@H_301_6@
  5. pthread_mutex_unlock(&mutex);//解锁@H_301_6@@H_301_6@@H_301_6@
  6. }@H_301_6@

3.3.释放@H_301_6@

在当前层的析构函数中:@H_301_6@

@H_301_6@

copy
    pthread_mutex_destroy(&mutex);@H_301_6@//前提要保证是解锁状态,否则会返回16的错误,释放失败@H_301_6@@H_301_6@@H_301_6@

这个时候再看一下结果,Bingo!@H_301_6@

@H_301_6@

copy
    BSell16@H_301_6@@H_301_6@
  1. ASell15@H_301_6@
  2. BSell14@H_301_6@
  3. BSell13@H_301_6@
  4. BSell12@H_301_6@
  5. BSell11@H_301_6@
  6. BSell10@H_301_6@
  7. BSell9@H_301_6@
  8. BSell8@H_301_6@
  9. BSell7@H_301_6@
  10. BSell6@H_301_6@
  11. BSell5@H_301_6@
  12. BSell4@H_301_6@
  13. BSell3@H_301_6@
  14. BSell2@H_301_6@
  15. BSell1@H_301_6@

4.源码下载@H_301_6@

http://download.csdn.net/detail/jackyvincefu/6503759@H_301_6@

猜你在找的Cocos2d-x相关文章