0
我在調試一些線程代碼,並且遇到了一些我不理解的行爲。爲什麼只有一個鎖和一個原子計數器會錯誤地喚醒條件變量?
我創建了一個線程向量。我有變量atomic_uint
Counter
和atomic_bool
Stop
,告訴線程什麼時候應該停止。每個線程線程在計數器不爲零的情況下等待,然後遞減它。
在主線程中,我增加Counter
,並且在條件下調用notify_one()
。代碼如下。
#include <thread>
#include <condition_variable>
#include <atomic>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <mutex>
int main() {
const std::size_t Tasks = 100u;
const std::size_t Repetitions = 100u;
const std::size_t Threads = 4u;
std::mutex Mutex;
std::condition_variable Condition;
std::atomic_uint Counter(0);
std::atomic_uint MainCounter(0);
std::atomic_uint ThreadCounter(0);
std::atomic_bool Stop(false);
std::vector<std::thread> v;
for (std::size_t i = 0; i < Threads; i++) {
v.emplace_back([&ThreadCounter,&Mutex, &Condition, &Counter, &Stop]() -> void {
while (true) {
{
std::unique_lock<std::mutex> lock(Mutex);
Condition.wait(lock, [&Counter, &Stop]() -> bool {
//wait while this is false
return Counter.load() >= 0u || Stop;
});
if (Stop && Counter == 0u) {
return;
}
ThreadCounter++;
if (Counter == 0) {
continue;
}
Counter--;
}
} //while
});
} //for
for (std::size_t i = 0u; i < Tasks; i++) {
MainCounter++;
Counter++;
Condition.notify_one();
}
while (Counter != 0u) {
std::this_thread::yield();
}
Stop = true;
Condition.notify_all();
for (auto& t: v) {
t.join();
}
std::cout << "ThreadCounter = " << ThreadCounter.load() << std::endl;
std::cout << "MainCounter = " << MainCounter.load() << std::endl;
return 0;
}
在線程代碼,我有一個額外的原子,ThreadCounter
,跟蹤的多少次Counter
實際上是遞減。
ThreadCounter
總是被增加更多倍Condition.notify_one()
被調用:
ThreadCounter = 212
MainCounter = 100
這是如何發生的時候,我用一個鎖鎖定的條件?據我所知,一次只有一個線程可以訪問Counter
(除了主線程)。