3

私はマルチスレッド アプリケーション (std::thread を使用) とマネージャー (クラス ツリー) を使用して、異なるサブツリー (組み込み構造体サブツリー) でコードの一部を並列に実行しています。基本的な考え方は、SubTree の各インスタンスにはオブジェクトを格納する両端キューがあるということです。両端キューが空の場合、スレッドは新しい要素が両端キューに挿入されるか、終了基準に達するまで待機します。1 つのサブツリーでオブジェクトを生成し、それらを別のサブツリーの両端キューにプッシュできます。便宜上、すべての std::mutex、std::locks、および std::variable_condition は「locks」と呼ばれる構造体に格納されます。

クラス Tree は、次のメソッドを実行するいくつかのスレッドを作成します (最初の試行) :

void Tree::launch(SubTree & st, Locks & locks )
{
/* some code */

std::lock_guard<std::mutex> deque_lock(locks.deque_mutex_[st.id_]) ; // lock the access to the deque of subtree st
if (st.deque_.empty())  // check that the deque is still empty
{
    // some threads are still running, wait for them to terminate

    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]) ;
    locks.restart_condition_[st.id_].wait(wait_lock) ;   
}

/* some code */
}

問題は、スレッドが待機している間、「deque_lock」がまだロックされていることです。したがって、並行スレッドによって現在のスレッドの両端キューにオブジェクトを追加することはできません。

そこで、lock_guard を unique_lock に変更し、手動でロック/ロック解除を管理しました。

void launch(SubTree & st, Locks & locks )
{
/* some code */

std::unique_lock<std::mutex> deque_lock(locks.deque_mutex_[st.id_]) ; // lock the access to the deque of subtree st
if (st.deque_.empty())          // check that the deque is still empty
{
    deque_lock.unlock() ; // unlock the access to the deque to enable the other threads to add objects

    // DATA RACE : nothing must happen to the unprotected deque here !!!!!!

    // some threads are still running, wait for them to terminate

    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]) ;
    locks.restart_condition_[st.id_].wait(wait_lock) ;   
}

/* some code */
} 

ここでの問題は、データ競合があることです。「待機」命令が「deque_lock.unlock()」命令の直後に実行されるようにしたいと思います。標準ライブラリでこのような重要な命令シーケンスを作成する方法を知っている人はいますか?

前もって感謝します。

4

1 に答える 1

-1

条件変数の待機から戻ったときに、待機していた条件が満たされていると想定しないことをお勧めします。

このコードを次のように記述します。

std::unique_lock<std::mutex> deque_lock(locks.deque_mutex_[st.id_]);
while(st.deque_.empty())
{
    deque_lock.unlock();
    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]);
    locks.restart_condition_[st.id_].wait(wait_lock);   
    deque_lock.lock();
}

このコードは、しばらくするとキューが空にならないことを保証します。std::condition_variable::waitこの王様の振る舞いをシミュレートする述語を取ることさえできます (ただし、キューのロックのため、ここでは使用できません)。

于 2012-06-11T22:40:03.047 に答える