1. 程式人生 > >cocos2dx多執行緒以及執行緒同步 與 cocos2dx記憶體管理與多執行緒問題

cocos2dx多執行緒以及執行緒同步 與 cocos2dx記憶體管理與多執行緒問題

ocos2d-x引擎在內部實現了一個龐大的主迴圈,每幀之間更新介面,如果耗時的操作放到了主執行緒中,遊戲的介面就會卡,這是不能容忍的,遊戲最基本的條件就是流暢性,這就是為什麼遊戲開發選擇C++的原因。另外現在雙核手機和四核手機越來越普遍了,是時候使用多執行緒來挖掘硬體的潛力了。

1.環境搭建

cocos2d-x中的多執行緒使用pthread就可以實現跨平臺,而且也不是很難理解。使用pthread需要先配置一下工程。右擊工程----->屬性----->配置屬性---->連結器----->輸入---->附加依賴項中新增pthreadVCE2.lib,如下圖


接著新增附加包含目錄,右擊專案,屬性----->C/C++---->常規----->附加包含目錄加入pthread標頭檔案所在的目錄


這樣,環境就搭建起來了。

2.多執行緒的使用

使用pthread來實現多執行緒,最重要的一個函式是

  1. PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,//執行緒的標示   
  2.                             const pthread_attr_t * attr,      //建立執行緒的引數   
  3.                             void *(*start) (void *),          //入口函式的指標   
  4.                             void
     *arg);                       //傳遞給執行緒的資料  
  1. PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,//執行緒的標示
  2.                             const pthread_attr_t * attr,      //建立執行緒的引數
  3.                             void *(*start) (void *),          //入口函式的指標
  4.                             void *arg);                       
    //傳遞給執行緒的資料

在HelloWorldScene.h檔案中
  1. pthread_t pidrun,pidgo;  
  2. static void* th_run(void *r);  
  3. static void* th_go(void *r);  
  1. pthread_t pidrun,pidgo;  
  2. staticvoid* th_run(void *r);  
  3. staticvoid* th_go(void *r);  
定義了兩個函式和兩個執行緒的標識。

然後自定義了一個類,用於給執行緒傳遞資料。Student類如下:

  1. #pragma once   
  2. #include <string>   
  3. class Student  
  4. {  
  5. public:  
  6.     Student(void);  
  7.     Student(std::string name,int age,std::string sex);  
  8.     ~Student(void);  
  9.     std::string name;  
  10.     int age;  
  11.     std::string sex;  
  12. };  
  1. #pragma once
  2. #include <string>
  3. class Student  
  4. {  
  5. public:  
  6.     Student(void);  
  7.     Student(std::string name,int age,std::string sex);  
  8.     ~Student(void);  
  9.     std::string name;  
  10.     int age;  
  11.     std::string sex;  
  12. };  

原始檔如下
  1. #include "Student.h"   
  2. #include "cocos2d.h"   
  3. Student::Student(void)  
  4. {  
  5. }  
  6. Student::~Student(void)  
  7. {  
  8.     cocos2d::CCLog("delete data");  
  9. }  
  10. Student::Student(std::string name,int age,std::string sex)  
  11. {  
  12.     this->name=name;  
  13.     this->age=age;  
  14.     this->sex=sex;  
  15. }  
  1. #include "Student.h"
  2. #include "cocos2d.h"
  3. Student::Student(void)  
  4. {  
  5. }  
  6. Student::~Student(void)  
  7. {  
  8.     cocos2d::CCLog("delete data");  
  9. }  
  10. Student::Student(std::string name,int age,std::string sex)  
  11. {  
  12.     this->name=name;  
  13.     this->age=age;  
  14.     this->sex=sex;  
  15. }  
在退出選單的回撥函式中啟動兩個執行緒:
  1. void HelloWorld::menuCloseCallback(CCObject* pSender)  
  2. {  
  3.     Student *temp=new Student(std::string("zhycheng"),23,std::string("male"));  
  4.     pthread_mutex_init(&mutex,NULL);  
  5.     pthread_create(&pidrun,NULL,th_run,temp);//啟動執行緒   
  6.     pthread_create(&pidgo,NULL,th_go,0);  
  7. }  
  1. void HelloWorld::menuCloseCallback(CCObject* pSender)  
  2. {  
  3.     Student *temp=new Student(std::string("zhycheng"),23,std::string("male"));  
  4.     pthread_mutex_init(&mutex,NULL);  
  5.     pthread_create(&pidrun,NULL,th_run,temp);//啟動執行緒
  6.     pthread_create(&pidgo,NULL,th_go,0);  
  7. }  

可以看到,將Student的指標傳遞給了pidrun執行緒,那麼在pidrun執行緒中獲得Student資訊如下:
  1.        Student *s=(Student*)(r);  
  2. CCLog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());  
  3. delete s;  
  1.        Student *s=(Student*)(r);  
  2. CCLog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());  
  3. delete s;  

3.執行緒同步

使用了執行緒,必然就要考慮到執行緒同步,不同的執行緒同時訪問資源的話,訪問的順序是不可預知的,會造成不可預知的結果。

這裡使用pthread_mutex_t來實現同步,下面我來演示一下使用多執行緒實現賣票系統。賣票的時候,是由多個視窗同時賣票,這裡要做到一張票不要賣出去兩次,不要出現有票卻無法賣的結果。

線上程函式th_run和th_go中來賣票,票的數量是一個全域性變數,每賣出去一張票,就將票的數量減一。其中同步的pthread_mutex_t也是一個全域性變數,就用它來實現執行緒同步。

  1. void* HelloWorld::th_run(void *r)  
  2. {  
  3.     Student *s=(Student*)(r);  
  4.     CCLog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());  
  5.     delete s;  
  6.     while(true)  
  7.     {  
  8.         pthread_mutex_lock(&mutex);  
  9.         if(ticket>0)  
  10.         {  
  11.         CCLog("thread run sell %d",ticket);  
  12.         ticket--;  
  13.         pthread_mutex_unlock(&mutex);  
  14.         }  
  15.         else  
  16.         {  
  17.             pthread_mutex_unlock(&mutex);  
  18.             break;    
  19.         }  
  20.         Sleep(1);  
  21.         //Usleep(10);   
  22.     }  
  23.     return NULL;  
  24. }  
  1. void* HelloWorld::th_run(void *r)  
  2. {  
  3.     Student *s=(Student*)(r);  
  4.     CCLog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());  
  5.     delete s;  
  6.     while(true)  
  7.     {  
  8.         pthread_mutex_lock(&mutex);  
  9.         if(ticket>0)  
  10.         {  
  11.         CCLog("thread run sell %d",ticket);  
  12.         ticket--;  
  13.         pthread_mutex_unlock(&mutex);  
  14.         }  
  15.         else
  16.         {  
  17.             pthread_mutex_unlock(&mutex);  
  18.             break;    
  19.         }  
  20.         Sleep(1);  
  21.         //Usleep(10);
  22.     }  
  23.     return NULL;  

來自:http://blog.csdn.net/kaitiren/article/details/14453313