强制同时修改变量 (C++)
Posted
技术标签:
【中文标题】强制同时修改变量 (C++)【英文标题】:Enforce concurrent modification of a variable (C++) 【发布时间】:2018-11-21 14:15:45 【问题描述】:我正在尝试对原子库进行单元测试(我知道原子库不适合进行单元测试,但我仍然想尝试一下)
为此,我想让 X 个并行线程增加一个计数器并计算结果值(应该是 X)。
代码如下。问题是它永远不会中断。 Counter
总是以 2000 结尾(见下文)。我还注意到cout
也作为一个整体打印(而不是混合在一起,我记得在其他多线程couts
中看到的)
我的问题是:为什么这不会中断?或者我怎样才能让它中断?
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool start = false;
int Counter = 0;
void Inc()
// Wait until test says start
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] return start; );
std::cout << "Incrementing in thread " << std::this_thread::get_id() << std::endl;
Counter++;
int main()
std::vector<std::thread> threads;
for (int i = 0; i < 2000; ++i)
threads.push_back(std::thread(Inc));
// signal the threads to start
std::lock_guard<std::mutex> lk(m);
start = true;
cv.notify_all();
for (auto& thread : threads)
thread.join();
// Now check whether value is right
std::cout << "Counter: " << Counter << std::endl;
结果看起来像这样(但后来有 2000 行)
Incrementing in thread 130960
Incrementing in thread 130948
Incrementing in thread 130944
Incrementing in thread 130932
Incrementing in thread 130928
Incrementing in thread 130916
Incrementing in thread 130912
Incrementing in thread 130900
Incrementing in thread 130896
Counter: 2000
任何帮助将不胜感激
更新:将线程的 nr 减少到 4,但在 for 循环中增加一百万次(如 @tkausl 所建议),线程 ID 的 cout
似乎是连续的。..
UPDATE2:事实证明,必须解锁锁以防止每个线程的独占访问 (lk.unlock()
)。 for 循环中的额外yield
增加了竞争条件效果。
【问题讨论】:
线程太多而做的太少。尝试使用两个或四个线程,每个线程在循环中将变量递增一百万次。 您正在尝试制作一个 heisenbug。没有 100% 的方法。 @tkausl Tnx,查看更新 coliru.stacked-crooked.com/a/4f0b8c68851694c6 【参考方案1】:cv.wait(lk, [] return start; );
仅返回获得的lk
。所以是排他的。你可能想在之后解锁lk
:
void Inc()
// Wait until test says start
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] return start; );
lk.unlock();
Counter++;
您必须删除std::cout
,因为它可能会引入同步。
【讨论】:
couts
似乎混合了一段时间。不过,还没有看到不一致的计数器。
@Ben 在我的电脑(E5-1620)上,它给出了 ~1999,但大部分是 2000。
在 for 循环中添加睡眠(请参阅更新)会有所帮助。现在终于不行了:)以上是关于强制同时修改变量 (C++)的主要内容,如果未能解决你的问题,请参考以下文章