9

2 つのスレッドと、2 番目のスレッドによって設定されるフラグがあります。を使用できますがatomic_bool、最初のスレッドでフラグが設定されるのを待つ*ことができるようにしたいです。どうやってやるの?

最初のスレッドが待機を開始する前にcondition_variable2 番目のスレッドが呼び出された場合、スレッドは起動しないため、使用できません。notify_one

また、フラグがすでに設定されているかどうかの確認は、かなり高速です。これはかなり単純なはずですが、行き詰まっているので、ここで質問しています。前もって感謝します。

*編集: もちろん、ビジー待機ではなくブロックします。わかりにくかったらごめんなさい。

4

3 に答える 3

12

cbreak と Ravadre (コメント) の助けを借りて、私はここから得ました:

int main()
{
    std::mutex m;
    std::condition_variable cv;

    std::thread t([&] {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            std::unique_lock<std::mutex> lock(m);
            cv.wait(lock);
            std::cout << "Yay!\n";
    });

    cv.notify_one();
    t.join();
}

ここまでは、通常はまったく終了しません。

int main()
{
    std::mutex m;
    std::condition_variable cv;
    bool flag = false;

    std::thread t([&] {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::unique_lock<std::mutex> lock(m);
        cv.wait(lock, [&] { return flag; });
        std::cout << "Yay!\n";
    });

    {
        std::lock_guard<std::mutex> lock(m);
        flag = true;
    }

    cv.notify_one();
    t.join();
}

これは実際に仕事をしますが、それでも多くの不必要なオーバーヘッドのようです。同等の、よりパフォーマンスの高い(またはよりエレガントな)回答を自由に投稿してください。喜んで受け入れます。ただし、標準 C++11 のみを使用してください。そうでない場合は、標準 C++11 でこれができない理由を説明してください。

編集:これをカプセル化するためのクラスsafe_flagも作成しました(cbreakに感謝します)。改善点があれば遠慮なく提案してください。

class safe_flag
{
    mutable std::mutex m_;
    mutable std::condition_variable cv_;
    bool flag_;

public:
    safe_flag()
        : flag_(false)
    {}

    bool is_set() const
    {
        std::lock_guard<std::mutex> lock(m_);
        return flag_;
    }

    void set()
    {
        {
            std::lock_guard<std::mutex> lock(m_);
            flag_ = true;
        }
        cv_.notify_all();
    }

    void reset()
    {
        {
            std::lock_guard<std::mutex> lock(m_);
            flag_ = false;
        }
        cv_.notify_all();
    }

    void wait() const
    {
        std::unique_lock<std::mutex> lock(m_);
        cv_.wait(lock, [this] { return flag_; });
    }

    template <typename Rep, typename Period>
    bool wait_for(const std::chrono::duration<Rep, Period>& rel_time) const
    {
        std::unique_lock<std::mutex> lock(m_);
        return cv_.wait_for(lock, rel_time, [this] { return flag_; });
    }

    template <typename Rep, typename Period>
    bool wait_until(const std::chrono::duration<Rep, Period>& rel_time) const
    {
        std::unique_lock<std::mutex> lock(m_);
        return cv_.wait_until(lock, rel_time, [this] { return flag_; });
    }
};
于 2013-02-17T12:29:30.780 に答える
7
bool go = false;
std::mutex mtx;
std::condition_variable cnd;

// waiting thread:
std::unique_lock<std::mutex> lck(mtx);
while (!go)
    cnd.wait(lock);
// when we get here we know that go is true, and we have the lock

// signalling thread:
{
std::unique_lock<std::mutex> lck(mtx);
go = true;
cnd.notify_one();
}
// now we've released the lock, so the waiting thread will make progress
于 2013-02-17T13:13:05.690 に答える
1

あなたのプラットフォームは正確には何ですか?私たちが使用するposix準拠のプラットフォームでは

  sem_t semaphore;
  sem_init( &semaphore , 0 , x );

x の初期値を持つセマフォを取得します。次に

 sem_wait(&semaphore ); sem_post(&semaphore);

2 つのスレッドを同期できます。両方のスレッドがアクセスできることを確認するために、グローバル変数として宣言することを忘れないでくださいsemaphore(または同じことを達成する他の手段によって)。

簡単に言えば、次のことができます。

sem_t semaphore;
sem_init(&semaphore, 0 , 0 );
void thread2(){
   sem_post(&semaphore);    //second thread --A
}
void thread1(){
    sem_wait(&semaphore);   // wait until thread2() executes line A
}

Win32でも同じことを達成するための同様のユーティリティがあるはずです。

于 2013-02-17T12:02:03.557 に答える