c++多线程访问布尔成员



由于低延迟要求,我使用并行执行for_each来识别句子(一组字符串)的意图。我以前学过,没有必要互斥锁来保护bool或任何数据类型,它的大小小于一个字节。我在问是否访问布尔成员标签。m_Found线程安全吗?否则,我应该使用原子还是互斥?

#include <iostream>
#include <unordered_set>
#include <set>
#include <list>
#include <algorithm>
#include <execution>
struct Tag{
const std::unordered_set<std::string> m_Context;
const std::string m_Name;
volatile bool m_Found;
Tag(const std::unordered_set<std::string> context, const std::string name)
: m_Context(context)
, m_Name(name)
, m_Found(false)
{}
Tag(const Tag & tag) = delete;
Tag(Tag && tag) = default;
Tag & operator=(const Tag & tag) = delete;
};
int main(){
const std::set<std::string> input = {"hello", "my", "son"};
std::list<Tag> intentions;
intentions.emplace_back(Tag({"hello", "Hi", "morning"}, "greeting"));
intentions.emplace_back(Tag({"father", "mother", "son"}, "family"));
intentions.emplace_back(Tag({"car", "bus", "airplan"}, "transportation"));
for_each( std::execution::par
, std::begin(input)
, std::end(input)
, [& intentions](const std::string & input_element)
{
for_each( std::execution::par
, std::begin(intentions)
, std::end(intentions)
, [& input_element](Tag & intention){
if(!intention.m_Found){
intention.m_Found = intention.m_Context.find(input_element)!=intention.m_Context.end();
}
}
);
}
);
for_each( std::execution::seq
, std::begin(intentions)
, std::end(intentions)
, [](Tag & intention){
if(intention.m_Found){
std::cout<<intention.m_Name;
}
}
);
return 0;
}

问题是如果添加"std::mutex m_Found_access;"或生成"atomic_bool m_Found;"默认的移动构造函数被删除了,所以我需要为Tag定义一个移动构造函数。并且m_Found应该只设置为true以避免竞争条件(如@Nate Eldredge所提到的)。代码变成:

#include <iostream>
#include <unordered_set>
#include <set>
#include <list>
#include <algorithm>
#include <execution>
struct Tag{
const std::unordered_set<std::string> m_Context;
const std::string m_Name;
std::atomic_bool m_Found;
Tag(const std::unordered_set<std::string> context, const std::string name)
: m_Context(context)
, m_Name(name)
, m_Found(false)
{}
Tag(const Tag & tag) = delete;
Tag & operator=(const Tag & tag) = delete;
Tag(Tag && tag) : m_Context(std::move(tag.m_Context))
, m_Name(std::move(tag.m_Name))
, m_Found(static_cast< bool >(tag.m_Found))
{}
};
int main(){
const std::set<std::string> input = {"hello", "my", "son"};
std::list<Tag> intentions;
intentions.emplace_back(Tag({"hello", "Hi", "morning"}, "greeting"));
intentions.emplace_back(Tag({"father", "mother", "son"}, "family"));
intentions.emplace_back(Tag({"car", "bus", "airplan"}, "transportation"));
for_each( std::execution::par
, std::begin(input)
, std::end(input)
, [& intentions](const std::string & input_element)
{
for_each( std::execution::par
, std::begin(intentions)
, std::end(intentions)
, [& input_element](Tag & intention){
if(!intention.m_Found){
if(intention.m_Context.find(input_element)!=intention.m_Context.end()){
intention.m_Found = true;
}
}
}
);
}
);
for_each( std::execution::seq
, std::begin(intentions)
, std::end(intentions)
, [](Tag & intention){
if(intention.m_Found){
std::cout<<intention.m_Name;
}
}
);
return 0;
}

最新更新