1

BoostマルチスレッドBoostアプリケーションを作成してWindowsまたはLinuxでコンパイルできることを知っているので、私はスレッドを試してpthreadsいます.

別の SO question から借用した次のサンプル アプリケーションがあります。


#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

#define NAP_DURATION    (10000UL)   // 10ms

boost::mutex io_mutex;

void count(int id)
{
    for (int i = 0; i < 1000; ++i)
    {
        boost::mutex::scoped_lock lock(io_mutex);
        std::cout << "Thread ID:" << id << ": " << i << std::endl;
        if (id == 1)
        {
            std::cout << "I'm thread " << id << " and I'm taking a short nap" << std::endl;
            usleep(NAP_DURATION);
        }
        else
        {
            std::cout << "I'm thread " << id << ", I drink 100 cups of coffee and don't need a nap" << std::endl;
        }
        std::cout << "Thread ID:" << id << ": " << i << std::endl;
        boost::thread::yield();
    }
}

int main(int argc, char* argv[])
{
    boost::thread thrd1( boost::bind(&count, 1));
    boost::thread thrd2( boost::bind(&count, 2));

    thrd1.join();
    thrd2.join();
    return 0;
}

次の方法で、Ubuntu 14.04 LTS システムに Boost をインストールしました。

sudo apt-get install libboost-all-dev

そして、次の方法で上記のコードをコンパイルします。

g++ test.cpp -lboost_system -lboost_thread -I"$BOOST_INLCUDE" -L"$BOOST_LIB"

いくつかの興味深い矛盾のように見えるものに出くわしました。longy NAP_DURATION、たとえば 1 秒 ( ) を設定すると、操作が完了するまで1000000スレッドのみがミューテックスを取得するように見えます。スレッドが完了するまでスレッドがロックを取得することは非常にまれです。数ミリ秒。121NAP_DURATION

を使用して同様のアプリケーションを作成しpthreadsた場合、別のスレッドがミューテックスで既にブロックされているため、通常、ロックはスレッド間で多かれ少なかれランダムに交互に行われます。


それで、質問に:

  1. これは予想される動作ですか?
  2. ロック操作がキューに入れられたようにスコープ ロックを動作させるなど、この動作を制御する方法はありますか?
  3. (2) に対する答えが「いいえ」の場合、条件変数を使用して同様のことを達成しBoost、ロック/ロック解除の呼び出しが失敗することを心配する必要はありませんか?
  4. scoped_lockロック解除は保証されていますか?どうやらロック解除操作が失敗して例外をスローする可能性があるため、手動でロック/ロック解除するのではなく、RAII アプローチを使用しています。このコードを確実なものにしようとしています。

ありがとうございました。

明確化

呼び出しスレッドをスリープ状態にしてもミューテックスのロックが解除されないことは承知していますが、それはまだスコープ内にあるためですが、予想されるスケジューリングは次のようなものでした。

  • Thread1 がロックし、mutex を取得します。
  • Thread2 のロック、ブロック。
  • Thread1 が実行され、ロックが解放され、すぐに再度ロックが試行されます。
  • スレッド 2 は既にロックを待機しており、スレッド 1 の前にロックを取得します。
4

2 に答える 2

1

なぜあなたは正確に驚いたのですか?スレッド 1 がスリープしている間にスレッド 2 がミューテックスを取得することを期待していた場合、はい、これは予期された動作であり、ロックがスコープ内にあるため、あなたの理解は間違っていました。

しかし、ループ反復の最後にスレッド 1 とスレッド 2 の間に交互性がないために驚いた場合は、「不公平」と思われるスケジューリングに関するこの SO の質問を見ることができます。

于 2015-06-23T16:28:22.733 に答える