Cocos2d-x 3.xにおけるマルチスレッドの基本実現構想


現在、以前のCocos 2 d-x 2に基づいて書き換える.x実装の小さなゲームは、マルチスレッドコードにかかわると、突然コンパイラがヘッダファイルが見つからないことを示すpthread.h.調べてみると、今の3.xではpthreadはサポートされていません.hヘッダファイル、以前の2.X時代このファイルは$(ProjectDir)....\cocos2dx\platform\third_partywin 32pthreadパスの下.
今、3.Xではstd::thread関連APIを直接使用することを推奨し,当然C++11簡略化処理後のマルチスレッドAPIである.
 
全体的な使用構想は以下の通りである.
--------------------------------------------------------------------------------
 
cococos 2 d-x 2.0時代にはpthreadライブラリを使用し、プラットフォーム間アプリケーションで広く使用されていたユーザーレベルのスレッドライブラリです.しかし、cococos 2 d-x 3.0ではpthreadのサポートファイルは発見されず、C++11にはスレッド操作のためのクラスstd::threadがよりよく使用されていた.cococos 2 d-x 3.0のバージョンのデフォルトはvs 2012バージョンで、C++11の新しい特性をサポートしており、std::threadを使用してスレッドを作成するのは便利です.
 
以下std::threadの簡単な使い方を紹介します.コードにはヘッダファイルが含まれています.
 
bool HelloWorld::init()   
{   
    if ( !Layer::init() )   
    {   
        return false;   
    }   
        
    std::thread t1(&HelloWorld::myThread,this);//      ,   myThread      
    t1.join();   
//  t1.detach();   
    
    CCLOG("in major thread");//       
    
    return true;   
}   
    
void HelloWorld::myThread()   
{   
    CCLOG("in my thread");   
}

--------------------------------------------------------------------------------
説明する
t.join()サブスレッドmyThreadが実行されるのを待ってから、メインスレッドは実行を続けることができ、このとき、メインスレッドは実行後のサブスレッドリソースを解放します.上の画像からもわかるように、「in my thread」を出力してから「in major thread」を出力します.
 
もちろん、サブスレッドを待ちたくない場合は、メインスレッド内でt 1を実行することができる.detach()はサブスレッドをプライマリスレッドから分離し、サブスレッドの実行が完了すると自分でリソースを解放します.分離されたスレッドでは、プライマリ・スレッドには制御権がありません.次のようになります.
 
std::thread t1(&HelloWorld::myThread,this);//ブランチスレッドを作成しmyThread関数のt 1にコールバックする.detach();--------------------------------------------------------------------------------
もちろん,スレッド関数にパラメータを通すこともでき,ここではbindを用いた.次の例では、スレッドオブジェクトをインスタンス化すると、スレッド関数myThreadの直後に2つのパラメータが入力されます.
 
bool HelloWorld::init()   
    {   
        if ( !Layer::init() )   
        {   
            return false;   
        }   
            
        std::thread t1(&HelloWorld::myThread,this,10,20);//        ,   myThread      
        t1.join();   
    //  t1.detach();   
        
        
        CCLOG("in major thread");//       
        return true;   
    }   
        
        
    void HelloWorld::myThread(int first,int second)   
    {   
        CCLOG("in my thread,first = %d,second = %d",first,second);   
    }

 
--------------------------------------------------------------------------------
 
反発オブジェクトによるデータの同期
 
この問題は主に1つのスレッドが半分に実行された場合、タイムスライスの切り替えにより別のスレッドが同じデータを変更し、元のスレッドを再び切り替えて下に実行し続けると、データが変更されたため結果エラーが発生するためです.だから私たちがしなければならないのは、このスレッドが完全に実行されることを保証することです.だから、スレッドのロックには良い注意です.反発オブジェクトmutexはこのロックです.
 
1)反発ロックの初期化
  std::mutex mutex;//スレッド反発オブジェクト
2)myThreadAとmyThreadBのコードを修正し、そこに反発ロックを追加する
 
void HelloWorld::myThreadA()
    {   
        while(true)     
        {     
            
mutex.lock();//  
   
            if(tickets>0)     
            {     
                Sleep(10);   
                CCLOG("A Sell %d",tickets--);//    ,   1     
                
mutex.unlock();//     
            }     
            else {     
                
mutex.unlock();  
 
                break;     
                    
            }     
        }     
    }   
    void HelloWorld::myThreadB()   
    {   
        while(true)     
        {     
            
mutex.lock(); 
  
            if (tickets>0)     
            {     
                Sleep(10);   
                CCLOG("B Sell %d",tickets--);     
                
mutex.unlock();
   
            }     
            else     
            {     
                
mutex.unlock(); 
  
                break;                 
            }     
        }     
    }

 
std::mutexには注意すべき点があります
 
オンラインスレッドAのstd::mutexはメンバー関数lockを使用してunlockをロックしてロックを解除し、よく機能しているように見えますが、これは安全ではありません.lockの後は必ずunlockを覚えなければなりませんが、それらの間に異常が発生したり、スレッドが直接unlockを脱退したりすると実行されません.この反発量は独占的なので、threadAがロックを解除する前に、この反発量ロックを使用する他のスレッドは、実行を待つことができません.
以上でまとめたのは,単純な反発ロックよりも複雑な場合については議論されていないC++11のサポート下でのマルチスレッドプログラミングの実現の基本状況にすぎない.