C++11マルチスレッドと同時制御

3988 ワード

C++11にはプラットフォームにまたがるスレッドライブラリとセットの同時制御ライブラリがパッケージされています.ここで一緒に記録します.
一、Threadライブラリ
C++11にはスレッドライブラリがパッケージされており、threadファイルにあり、基本的なスレッドに必要な各種関数があります.
基本的なスレッド操作の流れを以下に示します.
#include 
#include >
using namespace std;

void ThreadFunc(int nThreadNum)
{
	cout << "INFO: Num is " << nThreadNum << endl;
}

int main()
{
	thread TestThread(ThreadFunc, 1);
	cout << TestThread.get_id() << endl;

	TestThread.join();
	return 0;
}

スレッドの初期化時に入力される最初のパラメータは、スレッドが実行する関数であり、その後、可変パラメータがスレッド関数に使用されるパラメータを入力することができる.メインスレッドはget_を使用できますidは対応するスレッドidを取得し、このidはシステムが割り当てたidではなく、システムidを取得するには各オペレーティングシステムのオリジナルのインタフェースが必要であることに注意しなければならない.一般的な関数に加えて、クラスオブジェクトのメンバー関数も入力できます.
ThreadFuncObj TestObj;
thread TestThread(&ThreadFuncObj::ThreadFunc, &TestObj, 1);

上記のコードでは、ThreadFuncObj::ThreadFuncは非静的であるため、このタイプの関数ポインタを作成するために&を追加する必要があります.静的メンバー関数であれば追加しないでください.エディタはデフォルトで関数ポインタです.
二、反発量mutex
c++11はまた、マルチスレッドによる共有変数へのアクセス制御のためのmutexライブラリを提供する.すべての関連クラスはヘッダファイルにあります.全部で4つの反発クラスがあります
シーケンス番号
名前
用途
1
std::mutex
最も基本的で最もよく使われる反発クラス
2
std::recursive_mutex
同一スレッド内で再帰(再入)可能な反発クラス
3
std::timed_mutex
mutex機能に加え、タイムリミット要求ロック機能も備えています.
4
std::recursive_timed_mutex
同じスレッド内で再帰(再入)可能なtimed_mutex
基本操作はlock,try_lock,unlockの3種類である.簡単な例を次に示します
#include 
#include 
#include 
using namespace std;

void AddCount(mutex &mutexTest, int &nCount)
{
	for (int i = 0; i < 1000; ++i)
	{
		mutexTest.lock();
		++nCount;
		mutexTest.unlock();
	}
}

int main()
{
	thread arrThreads[5];
	mutex mutexTest;
	int nCount = 0;

	for (auto& threadIte : arrThreads)
	{
		threadIte = thread(AddCount, ref(mutexTest), ref(nCount));
	}
	for (thread& threadIte : arrThreads)
	{
		threadIte.join();
	}
	cout << nCount << endl;

	return 0;
}

上記の例ではlockをtry_に変更するとlockは、最終出力が5000未満になる可能性があります.また、2つの点に注意してください.
  • C++11に追加されたfor(a : b)という操作はpythonのfor a in bに似ています.ただし、aの値を変更するなど、bのaを遍歴操作する場合は、参照記号&を付ける必要があります.加えなくても操作できますが、オブジェクトはbの中のaではなくコピーのオブジェクトです.上記の例のように、threadIteは、threadがコピー構造をサポートしていないため、参照が付加されていない場合、エラーを報告する.
  • スレッドのパラメータについては、ref()で参照パラメータを識別する必要があります.そうしないと、
  • とエラーが発生します.
    三、MutexLockGuard
    C++のRAII特性は多くの場所で応用されており、mutexライブラリもlock_を提供している.guardクラスは、プログラムがコンストラクション関数でmutexをロックし、コンストラクションでロックを解除することを実現することができる.
    最も基本的なのはlock_guardテンプレート
    lock_guard _guard(mutexTest);
    

    lock_guardテンプレートは、mutexを操作するための最も基本的なRAII特性を提供します.さらにunique_を使用することもできますlock,unique_lockは、構造後にロックを解除するなど、より多くのインタフェースを提供し、構造が析出するまでロックを解除する必要はありません.
    unique_lock _guard(mutexTest);
    _guard.unlock();
    

    lock_よりguard,unique_lockはより柔軟になりますが、スペースと効率も遅くなります.
    四、条件変数waitとnotify
    C++11はまた、mutexに合わせて条件変数を提供し、信号量の制御機構を実現することができる.基本的な操作はwait+notify_one/notify_allです
    void AddCount(mutex& mutexTest, condition_variable &cv, int& nCount)
    {
    	for (int i = 0;i < 100; ++i)
    	{ 
    		unique_lock _guard(mutexTest);
    		nCount += 1;
    		cv.notify_one();
    	}
    }
    
    void Subcount(mutex& mutexTest, condition_variable& cv, int& nCount)
    {
    	for (int i = 0; i < 100; ++i)
    	{
    		unique_lock _guard(mutexTest);
    		if (nCount <= 0)
    			cv.wait(_guard);
    		nCount -= 0;
    	}
    }
    
    waitが呼び出されると、スレッドは入力された反発量をロック解除し、対応する信号量を待機し、他のスレッドのnotify信号を受信すると、反発量のロックを再試行し、wait以降のプログラムを実行する.
    条件変数condition_variableクラスを使用する場合は、unique_lockで提供される反発量クラスを使用する必要があります.他のタイプを使用する場合は、condition_variable_anyを使用します.