mutexは、condition_variable
の内部状態を保護します。 condition_variable
にwait
を呼び出すと、ミューテックスのロックが解除されます。待機中にスレッドはmutexを所有しません。
wait
が完了すると、wait
の呼び出しが戻る前に、ミューテックスが再び(アトミックに)取得されます。
スレッドは、ミューテックスと競合していないため、条件自体に競合しています。
あなたが望むなら待ってすぐにロックを解除することは自由です。たとえば、ある条件で複数のスレッドを同期させたい場合は、これを行う方法です。この機能を使用してセマフォを実装することもできます。
例:
このコードはnotify_all()
が行くこと10注意のバッチで物事を処理unlock()
後:
#include <condition_variable>
#include <mutex>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <vector>
void emit(std::string const& s)
{
static std::mutex m;
auto lock = std::unique_lock<std::mutex>(m);
std::cout << s << std::endl;
}
std::mutex m;
std::condition_variable cv;
int running_count = 0;
void do_something(int i)
{
using namespace std::literals;
auto lock = std::unique_lock<std::mutex>(m);
// mutex is now locked
cv.wait(lock, // until the cv is notified, the mutex is unlocked
[]
{
// mutex has been locked here
return running_count < 10;
// if this returns false, mutex will be unlocked again, but code waits inside wait() for a notify()
});
// mutex is locked here
++running_count;
lock.unlock();
// we are doing work after unlocking the mutex so others can also
// work when notified
emit("running " + std::to_string(i));
std::this_thread::sleep_for(500ms);
// manipulating the condition, we must lock
lock.lock();
--running_count;
lock.unlock();
// notify once we have unlocked - this is important to avoid a pessimisation.
cv.notify_all();
}
int main()
{
std::vector<std::thread> ts;
for (int i = 0 ; i < 200 ; ++i)
{
ts.emplace_back([i] { do_something(i); });
}
for (auto& t : ts) {
if (t.joinable()) t.join();
}
}
私は偉大な参照/サンプルサイトへご案内しましょう:のhttp:/ /en.cppreference.com/w/cpp/thread/condition_variable – NathanOliver
私の問題は解決しません。ごめんなさい。 –