• C++11多线程std::thread的简单使用


    http://www.cocoachina.com/cocos/20140523/8530.html

    【Cocos2d-x 3.0】C++11多线程std::thread的简单使用

    2014-05-23 17:01 编辑: wupeng 分类:Cocos引擎 来源:CocoaChina
     0 8773

    转自天涯海阁的博客

    本篇介绍的是线程!
     
    在cocos2d-x 2.0时代,我们使用的是pthread库,是一套用户级线程库,被广泛地使用在跨平台应用上。但在cocos2d-x 3.0中并未发现有pthread的支持文件,原来C++11中已经拥有了一个更好用的用于线程操作的类std::thread。cocos2d-x 3.0的版本默认是在vs2012版本,支持C++11的新特性,使用std::thread来创建线程简直方便。
     
    下面介绍下std::thread的一下简单用法,代码需包含头文件 
    1. bool HelloWorld::init()   
    2. {   
    3.     if ( !Layer::init() )   
    4.     {   
    5.         return false;   
    6.     }   
    7.        
    8.     std::thread t1(&HelloWorld::myThread,this);//创建一个分支线程,回调到myThread函数里   
    9.     t1.join();   
    10. //  t1.detach();   
    11.    
    12.    
    13.     CCLOG("in major thread");//在主线程   
    14.    
    15.    
    16.     return true;   
    17. }   
    18.    
    19. void HelloWorld::myThread()   
    20. {   
    21.     CCLOG("in my thread");   
    22. }   
     
    运行结果如下图: 
     
    t.join()等待子线程myThread执行完之后,主线程才可以继续执行下去,此时主线程会释放掉执行完后的子线程资源。从上面的图片也可以看出,是先输出"in my thread",再输出"in major thread"。
     
    当然了,如果不想等待子线程,可以在主线程里面执行t1.detach()将子线程从主线程里分离,子线程执行完成后会自己释放掉资源。分离后的线程,主线程将对它没有控制权了。如下:
     
    1. std::thread t1(&HelloWorld::myThread,this);//创建一个分支线程,回调到myThread函数里   
    2. t1.detach();   
     
    运行结果如下: 
     
    当然了,也可以往线程函数里穿参数,这里用到了bind。下面例子在实例化线程对象的时候,在线程函数myThread后面紧接着传入两个参数。
    1. bool HelloWorld::init()   
    2. {   
    3.     if ( !Layer::init() )   
    4.     {   
    5.         return false;   
    6.     }   
    7.        
    8.     std::thread t1(&HelloWorld::myThread,this,10,20);//创建一个分支线程,回调到myThread函数里   
    9.     t1.join();   
    10. //  t1.detach();   
    11.    
    12.    
    13.     CCLOG("in major thread");//在主线程   
    14.     return true;   
    15. }   
    16.    
    17.    
    18. void HelloWorld::myThread(int first,int second)   
    19. {   
    20.     CCLOG("in my thread,first = %d,second = %d",first,second);   
    21. }   
     
    输出结果如下图:  
     
    简单的东西我都说的差不多了,下面实际演练一下。请允许我参考偶尔E往事的一篇线程的博客, 他用的是pThread,这里我就用std::thread。
      
    售票
    总共有100张诺亚方舟船票,有2个售票点A和B在售票(一张票就一百亿美元吧),当票卖完了就结束了。我们知道当程序一开始进程就会创建一个主线程,所以可以在主线程基础上再创建2个线程A和B,再线程A和B中分别售票,当票数为0的时候,结束线程A和B。这里用cocos2d-x3.0和C++11的std::thread实现。
     
    多线程售票,代码如下:
    1. //HelloWorld.h   
    2. class HelloWorld : public cocos2d::Layer   
    3. {   
    4. public:   
    5.     static cocos2d::Scene* createScene();   
    6.     virtual bool init();     
    7.        
    8.     CREATE_FUNC(HelloWorld);   
    9.    
    10.     void myThreadA();//线程A   
    11.     void myThreadB();//线程B   
    12.    
    13.     int tickets;//票数     
    14.    
    15. };   
    16.    
    17. //.cpp   
    18. bool HelloWorld::init()   
    19. {   
    20.     if ( !Layer::init() )   
    21.     {   
    22.         return false;   
    23.     }   
    24.        
    25.     tickets = 100;//100张票   
    26.    
    27.     std::thread tA(&HelloWorld::myThreadA,this);//创建一个分支线程,回调到myThread函数里   
    28.     std::thread tB(&HelloWorld::myThreadB,this);   
    29.     tA.detach();   
    30.     tB.detach();   
    31. //  t1.detach();   
    32.    
    33.     CCLOG("in major thread");//在主线程   
    34.     return true;   
    35. }   
    36.    
    37. void HelloWorld::myThreadA()   
    38. {   
    39.     while(true)     
    40.     {     
    41.         if(tickets>0)     
    42.         {     
    43.             Sleep(10);   
    44.             CCLOG("A Sell %d",tickets--);//输出售票,每次减1     
    45.         }     
    46.         else {     
    47.             break;     
    48.         }     
    49.     }     
    50. }   
    51. void HelloWorld::myThreadB()   
    52. {   
    53.     while(true)     
    54.     {     
    55.         if (tickets>0)     
    56.         {     
    57.             Sleep(10);   
    58.             CCLOG("B Sell %d",tickets--);     
    59.         }     
    60.         else      
    61.         {     
    62.             break;     
    63.         }     
    64.     }     
    65. }   
     
    代码很简单,不多说了。我们来看一下输出,会发现有很多喜闻乐见的现象出现,因为每个人每次运行的结果都不一样,所以这里不贴结果了,其中比较有意思的现象是同一张票卖了两次?!
     
    原因不多解释了,时间片的问题,不明白的Google之。如果你觉得不会有这么巧,那么在打印结果前加上这么一句: 
    1. Sleep(100);   
     
    运行结果如图所示:
     
    利用互斥对象同步数据
    这个问题主要是因为一个线程执行到一半的时候,时间片的切换导致另一个线程修改了同一个数据,当再次切换会原来线程并继续往下运行的时候,数据由于被修改了导致结果出错。所以我们要做的就是保证这个线程完全执行完,所以对线程加锁是个不错的注意,互斥对象mutex就是这个锁。
     
    1)初始化互斥锁
    1. std::mutex mutex;//线程互斥对象   
     
    2)修改myThreadA与myThreadB的代码,在里面添加互斥锁
    1. void HelloWorld::myThreadA()   
    2. {   
    3.     while(true)     
    4.     {     
    5.         mutex.lock();//加锁   
    6.         if(tickets>0)     
    7.         {     
    8.             Sleep(10);   
    9.             CCLOG("A Sell %d",tickets--);//输出售票,每次减1     
    10.             mutex.unlock();//解锁   
    11.         }     
    12.         else {     
    13.             mutex.unlock();   
    14.             break;     
    15.                
    16.         }     
    17.     }     
    18. }   
    19. void HelloWorld::myThreadB()   
    20. {   
    21.     while(true)     
    22.     {     
    23.         mutex.lock();   
    24.         if (tickets>0)     
    25.         {     
    26.             Sleep(10);   
    27.             CCLOG("B Sell %d",tickets--);     
    28.             mutex.unlock();   
    29.         }     
    30.         else      
    31.         {     
    32.             mutex.unlock();   
    33.             break;                 
    34.         }     
    35.     }     
    36. }   
     
    运行结果如下,完美!
     
  • 相关阅读:
    1442. Count Triplets That Can Form Two Arrays of Equal XOR
    1441. Build an Array With Stack Operations
    312. Burst Balloons
    367. Valid Perfect Square
    307. Range Sum Query
    1232. Check If It Is a Straight Line
    993. Cousins in Binary Tree
    1436. Destination City
    476. Number Complement
    383. Ransom Note
  • 原文地址:https://www.cnblogs.com/wanqieddy/p/4595569.html
Copyright © 2020-2023  润新知