cocos2d-x 多線程以及線程同步


轉自:http://blog.csdn.net/zhy_cheng/article/details/9116479

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

1.環境搭建

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

 

接着添加附加包含目錄,右擊項目,屬性----->C/C++---->常規----->附加包含目錄加入pthread頭文件所在的目錄

 

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

2.多線程的使用

使用pthread來實現多線程,最重要的一個函數是

PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,//線程的標示
                            const pthread_attr_t * attr,      //創建線程的參數
                            void *(*start) (void *),          //入口函數的指針
                            void *arg);                       //傳遞給線程的數據

在HelloWorldScene.h文件中

pthread_t pidrun,pidgo;
static void* th_run(void *r);
static void* th_go(void *r);

定義了兩個函數和兩個線程的標識。

然后自定義了一個類,用於給線程傳遞數據。Student類如下:

#pragma once
#include <string>
class Student
{
public:
    Student(void);
    Student(std::string name,int age,std::string sex);
    ~Student(void);

    std::string name;
    int age;
    std::string sex;

};

源文件如下

#include "Student.h"
#include "cocos2d.h"

Student::Student(void)
{
}


Student::~Student(void)
{
    cocos2d::CCLog("delete data");
}
Student::Student(std::string name,int age,std::string sex)
{
    this->name=name;
    this->age=age;
    this->sex=sex;
}

在退出菜單的回調函數中啟動兩個線程:

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
   
    Student *temp=new Student(std::string("zhycheng"),23,std::string("male"));
    pthread_mutex_init(&mutex,NULL);
    pthread_create(&pidrun,NULL,th_run,temp);//啟動線程
    pthread_create(&pidgo,NULL,th_go,0);

}

可以看到,將Student的指針傳遞給了pidrun線程,那么在pidrun線程中獲得Student信息如下:

Student *s=(Student*)(r);
CCLog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());
delete s;

3.線程同步

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

 

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

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

void* HelloWorld::th_run(void *r)
{
    
    Student *s=(Student*)(r);
    CCLog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());
    delete s;
    while(true)
    {
        pthread_mutex_lock(&mutex);
        if(ticket>0)
        {
        CCLog("thread run sell %d",ticket);
        ticket--;
        pthread_mutex_unlock(&mutex);
        }
        else
        {
            pthread_mutex_unlock(&mutex);
            break;    
        }
    
        Sleep(1);
        //Usleep(10);
    }

    return NULL;
}
void* HelloWorld::th_go(void *r)
{
    
    while(true)
    {
        pthread_mutex_lock(&mutex);
        if(ticket>0)
        {
        CCLog("thread go sell %d",ticket);
        ticket--;
        pthread_mutex_unlock(&mutex);
        }
        else
        {
            pthread_mutex_unlock(&mutex);
            break;
            
        }
        
        Sleep(1);
        
    }
    return NULL;
}

mutex被鎖定后,其他線程若再想鎖定mutex的話,必須等待,當該線程釋放了mutex之后,其他線程才能鎖定mutex。Sleep()函數可以使得該線程休眠,單位是毫秒。下面是賣票的結果:

name is zhycheng,and age is 23,sex is male
delete data
thread run sell 100
thread run sell 99
thread go sell 98
thread go sell 97
thread run sell 96
thread go sell 95
thread go sell 94
thread run sell 93
thread go sell 92
thread run sell 91
thread go sell 90
thread go sell 89
thread run sell 88
thread go sell 87
thread run sell 86
thread go sell 85
thread run sell 84
thread go sell 83
thread run sell 82
thread go sell 81
thread run sell 80
thread go sell 79
thread run sell 78
thread go sell 77
thread run sell 76
thread go sell 75
thread run sell 74
thread go sell 73
thread run sell 72
thread go sell 71
thread run sell 70
thread go sell 69
thread go sell 68
thread run sell 67
thread go sell 66
thread run sell 65
thread go sell 64
thread run sell 63
thread go sell 62
thread run sell 61
thread go sell 60
thread run sell 59
thread go sell 58
thread run sell 57
thread go sell 56
thread run sell 55
thread go sell 54
thread run sell 53
thread run sell 52
thread go sell 51
thread run sell 50
thread go sell 49
thread run sell 48
thread go sell 47
thread run sell 46
thread go sell 45
thread run sell 44
thread run sell 43
thread go sell 42
thread run sell 41
thread run sell 40
thread go sell 39
thread run sell 38
thread run sell 37
thread run sell 36
thread run sell 35
thread go sell 34
thread run sell 33
thread run sell 32
thread go sell 31
thread run sell 30
thread run sell 29
thread run sell 28
thread run sell 27
thread run sell 26
thread run sell 25
thread go sell 24
thread run sell 23
thread go sell 22
thread go sell 21
thread run sell 20
thread go sell 19
thread run sell 18
thread run sell 17
thread go sell 16
thread run sell 15
thread go sell 14
thread go sell 13
thread run sell 12
thread go sell 11
thread go sell 10
thread run sell 9
thread go sell 8
thread run sell 7
thread go sell 6
thread go sell 5
thread run sell 4
thread go sell 3
thread run sell 2
thread run sell 1

可以看到,這個打印結果正確無誤。如果不加mutex會是什么樣的結果呢,我將線程同步的mutex注釋掉,輸出的結果為:

name is zhycheng,and age is 23,sex is male
delete data
thread run sell 100
thread run sell 99
thread run sell 98
thread go sell 97
thread run sell 96
thread go sell 95
thread run sell 94
thread go sell 94
thread run sell 92
thread run sell 91
thread go sell 90
thread run sell 89
thread go sell 88
thread run sell 87
thread run sell 86
thread go sell 86
thread go sell 84
thread run sell 83
thread go sell 82
thread run sell 81
thread go sell 80
thread run sell 79
thread run sell 78
thread go sell 77
thread run sell 76
thread run sell 75
thread go sell 74
thread run sell 73
thread go sell 72
thread run sell 71
thread go sell 70
thread go sell 69
thread run sell 68
thread go sell 67
thread go sell 66
thread run sell 65
thread go sell 64
thread go sell 63
thread run sell 62
thread go sell 61
thread run sell 60
thread run sell 59
thread run sell 58
thread run sell 57
thread run sell 56
thread run sell 55
thread go sell 54
thread run sell 54
thread go sell 52
thread run sell 52
thread go sell 50
thread run sell 50
thread go sell 49
thread run sell 47
thread go sell 47
thread go sell 45
thread run sell 45
thread run sell 43thread go sell 43

thread run sell 41
thread go sell 41
thread go sell 39
thread run sell 39
thread run sell 37
thread go sell 37
thread go sell 35
thread run sell 35
thread go sell 33thread run sell 33

thread go sell 31thread run sell 31

thread go sell 29
thread run sell 29
thread go sell 27
thread run sell 27
thread go sell 25
thread run sell 25
thread run sell 23
thread go sell 23
thread run sell 21
thread go sell 21
thread go sell 19
thread run sell 19
thread run sell 17
thread go sell 17
thread go sell 15
thread run sell 15
thread run sell 13
thread go sell 13
thread run sell 11thread go sell 11

thread go sell 9
thread run sell 9
thread run sell 7
thread go sell 7
thread go sell 5thread run sell 5

thread go sell 3
thread run sell 3
thread go sell 1
thread run sell 1

可以看到,有的票賣了兩次,有的票就沒賣。

 

4.注意

1.Sleep()函數是使得線程休眠的函數,這個函數不跨平台,僅僅在windows上能用,其他平台使用usleep。

2.在非主線程中不能使用cocos2d-x管理內存的CCObject::retain()CCObject::release() 者CCObject::autorelease(),因為CCAutoreleasePool不是線程安全的,OPENGL的上下文也不是線程安全的,所以不要再非主線程中使用cocos2d-x的API和UI操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM