C++ 为什么线程消毒剂会抱怨这个std::ranges::views::filter代码?
运行此代码时,线程消除器将处理有关数据竞争的问题。 为什么?C++ 为什么线程消毒剂会抱怨这个std::ranges::views::filter代码?,c++,race-condition,c++20,range-v3,C++,Race Condition,C++20,Range V3,运行此代码时,线程消除器将处理有关数据竞争的问题。 为什么? #包括 #包括 #包括 #包括 int main(){ std::向量v{11,22,33,44,55,66}; 自动查看=v |标准::范围::视图::过滤器([](常量自动x){ 返回x>47; }); std::jthread jt1([&]{ 整数和=0; 对于(const auto&val:view){sum+=val;} }); std::jthread jt2([&]{ 整数和=0; 对于(const auto&
#包括
#包括
#包括
#包括
int main(){
std::向量v{11,22,33,44,55,66};
自动查看=v |标准::范围::视图::过滤器([](常量自动x){
返回x>47;
});
std::jthread jt1([&]{
整数和=0;
对于(const auto&val:view){sum+=val;}
});
std::jthread jt2([&]{
整数和=0;
对于(const auto&val:view){sum+=val;}
});
}
注:我知道这个问题的答案,我最近在一次演讲中了解到了这个问题,但我发现它非常令人惊讶,并且没有任何与此相关的问题,所以我想与大家分享。如果没有人对回答感兴趣,我会自己回答。
[&]
在运行lambda的线程中,应该会立即发出警报。通过非const
引用将随机对象传递给线程通常是不安全的。特别是,在标准库对象上调用非const
成员函数不是线程安全的
begin
不是std::ranges::filter\u视图的const
成员函数
constexpr迭代器begin()代码>
应为:pred\u.has\u value()
返回:{*this,ranges::find_if(base_u,ref(*pred_u))}
备注:为了提供范围概念要求的摊销固定时间复杂性,
此函数将结果缓存在filter\u视图中
,以便在后续调用中使用
在libstdc++实现中,正是这个缓存操作触发了线程清理程序
试图使视图
恒定会导致编译错误
反向视图
也是如此
其他范围适配器的const
重载用于begin
实际上,在构造线程之前,可以通过调用view.begin()
来解决这个问题。我不知道这是否会使未定义的行为正式消失(我认为可能应该),但它确实让消毒剂保持沉默
#include <iostream>
#include <ranges>
#include <thread>
#include <vector>
int main(){
std::vector v{11,22,33,44,55,66};
auto view = v | std::ranges::views::filter([](const auto x){
return x>47;
});
std::jthread jt1([&]{
int sum =0;
for (const auto& val: view) {sum+=val;}
});
std::jthread jt2([&]{
int sum =0;
for (const auto& val: view) {sum+=val;}
});
}