複数のスレッドが存在するため、マルチスレッドアプリケーションは、スレッドまたは別のスレッドが操作の生成が完了した後、対応するアクションを取ることができる、スレッド間で同じ変数へのアクセスを必要とすることができます。
以下のような:いくつかのスレッドが計算集約コードセグメント、長い時間を実行し、他のスレッドが保護する必要があり、これは、スレッドの同期の概念であるの実行中に中断されないようにします。
Qtは、クラスがQMutex、QMutexLocker、QReadWriterLock、QReadLocker、QWriterLocker、QWaitCondition、QSemaphore含む、スレッド同期機能の複数を実現することができます。
また、それは提供QtConcurrent高レベルAPIをマルチスレッドプログラミングを達成するために、マルチスレッドプログラムが自動的にプロセッサコアの数に基づいてスレッドの数を調整することができます。
1.QMutexとQMutexLockerは、ミューテックススレッド同期クラスに基づいています。例QMutex定義は、ミューテックスです
QMutexは、主に3つの機能を提供します。
1)ロック():別のスレッドがミューテックスをロックしている場合、ミューテックスロックは、それがミューテックスのロックを解除するために別のスレッドまで実行をブロックします
2)ロック解除():ミューテックスのロックを解除
3)のtryLock():すでに別のスレッドによってロックされている場合、falseを返します成功した場合はtrueを返し、mutexをロックしようとする、しかし、実行をブロックしません。
// mythreadクラス:
民間:
QMutexミューテックス//セマフォ
元のメインスレッド関数データ取得スレッド信号にスロットを介して(EMIT(値)スレッド)
メインスレッドは、新しいデータクエリを読み続けて
実行( )
{
////
IF(XXX){
ミューテックス。ロック();
//データ処理
ミューテックス。ロック解除();
}
}
ブールXXX :: readValue()
{
もし(ミューテックス。のtryLock() )
{
// xxxxxxxxxxxxxxxxxxx
ミューテックス。ロック解除() 。
trueを返します。
}
他
falseを返します
}
2. QMutexLockerミューテックスは、簡略化したプロセスのクラスです。QMutexLockerのコンストラクタは、パラメータとしてミューテックスロックを受け取る QMutexLockerデストラクタがこのmutexのロックが解除され、。QMutexLockerにインスタンス変数のライフタイムコードセグメントは、保護されて自動的に入り、相互排他ロックとロック解除を。
上記の読み取りの例:
実行()
{
////
IF(XXX){
QMutexLockerロッカー(&ミューテックス)。 // mutex.lock();
//データ処理
// mutex.unlock();
}
}
3. QReadWriteLock
1つのスレッドしかミューテックスの使用権、プログラムを取得し、変数を読んで、ミューテックスを使用するために、複数のスレッドがある場合は、あなたはまた、キューイングしなければなりません。ちょうど変数を読み込む場合は、複数のスレッドが同時にアクセスすることができ、またはミューテックスは、アプリケーションのパフォーマンスが低下します。
QReadWriteLock 同期方法は、読み取りまたはコードの一部を保護する方法を記述するために、読み取りまたは書き込みロックを可能にする、ことができます複数のスレッドがする読み取り専用の同期リソースへのアクセスを、しかし限りするスレッドが存在するようなリソースへのアクセスを書き込み、他のスレッドがしなければならないまで待ちます書き込み動作は終了します。
これは、次の機能を提供します。
lockForRead():読み取り専用のリソースをロックし、ロックを書くために、他のスレッドがある場合は、この関数はブロックします
lockForWrite():このスレッドと他のスレッドのロックリソースモードを読み書きする場合、この機能はブロックされ、ロックされたリソースへの書き込み
アンロック():ロック解除
tryLockForRead():lockForRead、非ブロッキングバージョン
tryLockForWrite():lockForWrite、非ブロッキングバージョン
例えば:
QReadWriteLockロック;
スレッドA:実行()
{
Lock.lockForWrite()// BとCが同時に遮断されます
//書き込みデータ
施錠開錠()
}
threadB:実行()
{
Lock.lockForRead()// Aが書き込みモードでロックすることはできませんがブロックされています
//読み込んだデータ
施錠開錠()
}
threadC:実行()
{
Lock.lockForRead()
//読み込んだデータ
施錠開錠()
}
4. QReadLockerとQWriteLockerはQMutexのような単純なバージョンであるQReadWriteLock類似QMutexLockerを形成することが容易です。
QReadWriteLockロック;
スレッドA:実行()
{
QWriteLocerロッカー(&ロック)// BとCを同時に遮断し
//書き込みデータ
}
threadB:実行()
{
QReadLocerロッカー(&ロック)// Aが書き込みモードでロックすることはできませんがブロックされています
//読み込んだデータ
}
threadC:実行()
{
QReadLocerロッカー(&ロック)
//読み込んだデータ
}
一般プロデューサ/コンシューマ(プロデューサ/コンシューマ)モデルに使用5.QWaitCondition:メーカー生成データ、消費者データ
マルチスレッドのプログラムは、複数のスレッドの同期は、それらの間の実際の調整です。
プログラムスレッドよりも多くのリソースのロックを解除した後、速やかにない他のスレッドに通知
QWaitConditionは別の改良されたスレッド同期化方法を提供します。
特定の条件が満たされたときQWaitConditionとQMutex組み合わせは、それが唯一のミューテックスより高い使用するよりも、適切かつタイムリー、効率的に、他のスレッドの数がスレッドに通知することができ
これは、次の機能を提供します。
1)(QMutex * lockedMutex)待つミューテックスlockedMutexのロックを解除し、ブロックlockedMutexウェイクアップロックした後、ウェイクアップ条件を待っていると、機能を終了
2)wakeAll()は、すべてのスレッドが待機状態にある目覚め、不確実性の糸ウェイクの順序は、オペレーティングシステムのスケジューリングポリシーの決定があります
3)wakeOne()は、オペレーティングシステムのスケジューリングポリシーによって決定され、不確実な目覚め待機状態のスレッドを、目を覚まします
QMutexミューテックス
QWaitConditon newdataAvailable
スレッドA ::実行()
{
ミューテックス、ロック()
//データを取得します。
mutex.unlock()
newdataAvaliable.wakeAll()//新しいデータのウェイクアップすべてのスレッド
}
threadB ::実行()
{
mutex.lock()
newdataAvailable.wat(&ミューテックス)他のスレッドがミューテックスを使用できるように//最初のミューテックスのロックを解除
newValueが()方法のうち通過するデータ信号を送信し、データを読み出す//発します
mutex.unlock()
}
注意:threadConsumer.start()//最初に開始する必要があり、最初の待機状態に入ります
threadProducer.start()//開始後、内部wakeAll時間は、threadConsumerは、それ以外の場合は、データを失うことになる、タイムリーに対応することができなければなりません
threadProducer.stopThread()
threadProducer.wait()
threadConsumer.terminate()//強制年末まで待っている状態で終了することができます
threadConsumerは、)(待ちます
7セマフォセマフォスレッドの同期
セマフォは、共有リソースへのアクセスを制限するために、別のスレッド同期機構であり、似ていますが、ミューテックスとの違いがあります
ミューテックスはセマフォを複数回使用することができ、一度ロックすることができます。セマフォは、典型的には、同じリソースの特定の数、ダブルバッファなどのデータ収集を保護するために使用されます。
これは、次の機能を提供します。
非常に多くのリソースがあるまで1)を取得する(INTのN)リソースを取得しようとし、そうでない場合はあまりリソース、プログラムがブロックされます
2)リリース(int型n)はn個のリソース解放セマフォを再リリース後利用可能なすべてのリソースを持っている場合、あなたは利用可能なリソースの数を増やすために、より多くのリソースを作成することができます
3))(使用可能INTには、現在利用可能なリソースが存在しないことを示す、== 0、この数は決して負であり、電流ループ信号量のために利用可能なリソースの数を返します
4)BOOL tryAcquire(INT N = 1)N、スレッドをブロックしない失敗したリソースを取得することを試みます
QSemaphore WC(5)//WC.available()= 5
WC.acquire(4)//WC.available()= 1
WC.release(2)//WC.available()= 3
WC.acquire(3)//WC.available()= 0
WC.tryAcquire(1)//WC.available()は偽0戻ります=
WC.acquire()//WC.available()= 0ブロッキングリソース利用可能
n個のリソースセマフォは、共有リソースは、リソースを割り当てる方法として、問題の内部処理で、保護されるべきです
例:
ダブルバッファアナログデータ収集カード
//共有可変領域:
const int型たBufferSize = BUF_SIZE
int型BUF1 [たBufferSize]
int型BUF2 [たBufferSize]
int型CurBuf = 1 //バッファは、現在書き込まれています
int型BUFNO = 0 //データ領域IDを取得します
QSemaphore emptyBufsは、[2] //セマフォ バッファの数の空 リソース2の初期数
QSemaphore fullBufs //セマフォ バッファの数は、完全な リソース0の初期数
QThreadDA ::実行()//データ取得スレッド
{
m_stop = falseは、m_stop = falseを//スレッドを開始
BUFNO = 0; //バッファID
curBuf = 1 //現在の書き込みバッファが使用されています
INT、N = emptyBufs.available()。
IF(N <2)
emptyBufs.release(2-n)は、//スレッドを確保することはempty.avaliable == 2を起動します
しばらく(!m_stop)
{
emtpyBufs.acquire(); //は空のバッファを取得します
データの生成(i = 0; iがたBufferSizeを<; I ++は):
{IF(curBuf == 1)
BUF1 [i]は=新しいデータ収集
他
BUF2 [i]は=新しいデータ収集
}
BUFNO ++;
もし(curBuf == 1)
curBuf = 2
他
curBuf = 1
利用できるフルバッファ付きfullBufs.releasse()// = 1
}
}
//実際の条件下では、既存の操作が速く取得スレッドの速度よりも読まれるべきです
QThreadShow ::実行()
{
m_stop =偽
INT、N = fullBufs.available()
IF(N> 0)
利用可能なリソースの数がゼロに初期化されfullBuf fullBufs.acquire(N)//
しばらく(!m_stop)
{
ときfullBufs.available = 0閉塞fullBufs.acquire()//バッファを待つがいっぱいです
int型データ【BufSizeと】
int型配列= BUFNO
現在のバッファにおける(curBuf == 1)//がバッファに書き込まれる場合は、完全では、1 2
ために(..)
データは、【私は】【I】= BUF2
他
ために(..)
データは、【私は】【I】= BUF1
emptyBufs.release()//空のバッファを解放
(データ、データサイズ、SEQ)newviewを発します。
}
}