我们在这个线程上问正确的问题吗???如果是这样:他们的回答是否正确???
或者换一种说法:
我完全误解了这里的东西吗?
编辑段落:似乎StatementOnOrder(见下文)是错误的。请参阅链接 1 (Linux 下的 C++ 线程等通常基于 pthreads)和链接 2(将当前调度策略作为决定因素)——感谢来自cppreference ( ref ) 的Cubbi。另请参阅链接、链接、链接、链接。如果该语句为假,那么拉原子(!)票的方法,如下面的代码所示,可能是首选!
开始...
StatementOnOrder:“多个线程遇到锁定的互斥体并因此按特定顺序“进入睡眠状态”,随后将获得互斥体的所有权并以相同的顺序继续运行。
问题:StatementOnOrder是真还是假???
void myfunction() {
std::lock_guard<std::mutex> lock(mut);
// do something
// ...
// mutex automatically unlocked when leaving funtion.
}
我问这个是因为迄今为止此页面上的所有代码示例似乎都是:
a) 浪费(如果StatementOnOrder为真)
或者
b) 严重错误(如果StatementOnOrder为假)。
那么,如果StatementOnOrder为假,为什么还要说他们可能“严重错误”呢?
原因是所有代码示例都认为他们通过使用 来超级聪明std::condition_variable
,但实际上在此之前使用了锁,这会(如果StatementOnOrder为 false)弄乱了顺序!!!
只需在此页面上搜索std::unique_lock<std::mutex>
,即可看到讽刺意味。
所以如果StatementOnOrder真的是假的,你就不能遇到锁,然后再处理票证和条件变量的东西。相反,你必须做这样的事情:在遇到任何锁之前拉一张原子票!!!
为什么要在撞锁之前拉票?因为这里我们假设StatementOnOrder为假,所以任何排序都必须在“邪恶”锁之前完成。
#include <mutex>
#include <thread>
#include <limits>
#include <atomic>
#include <cassert>
#include <condition_variable>
#include <map>
std::mutex mut;
std::atomic<unsigned> num_atomic{std::numeric_limits<decltype(num_atomic.load())>::max()};
unsigned num_next{0};
std::map<unsigned, std::condition_variable> mapp;
void function() {
unsigned next = ++num_atomic; // pull an atomic ticket
decltype(mapp)::iterator it;
std::unique_lock<std::mutex> lock(mut);
if (next != num_next) {
auto it = mapp.emplace(std::piecewise_construct,
std::forward_as_tuple(next),
std::forward_as_tuple()).first;
it->second.wait(lock);
mapp.erase(it);
}
// THE FUNCTION'S INTENDED WORK IS NOW DONE
// ...
// ...
// THE FUNCTION'S INDENDED WORK IS NOW FINISHED
++num_next;
it = mapp.find(num_next); // this is not necessarily mapp.begin(), since wrap_around occurs on the unsigned
if (it != mapp.end()) {
lock.unlock();
it->second.notify_one();
}
}
上面的函数保证了订单按照拉取的原子票执行。(编辑:使用 boost 的侵入式映射,将 condition_variable 保留在堆栈上(作为局部变量),将是一个很好的优化,可以在这里使用,以减少免费存储的使用!)
但主要问题是:StatementOnOrder是真的还是假的???
(如果是真的,那么我上面的代码示例也是一种浪费,我们可以只使用互斥锁并完成它。)
我希望像Anthony Williams这样的人会检查这个页面......;)