c++ - 用不同的线程填充 std::vector
问题描述
我需要在不同的线程上填充一个 std::vector。
它是正确的代码吗?或者我应该为我的代码添加互斥锁?
void func(int i, std::vector<float>& vec)
{
vec[i] = i;
}
int main()
{
std::vector<float> vec(6);
std::list<std::thread> threads;
for (int i = 0; i < 6; i++)
{
threads.push_back(std::thread(func, i, std::ref(vec)));
}
for (auto iter = threads.begin(); iter != threads.end(); iter++)
{
(*iter).join();
}
}
我测试了我的代码,它工作正常。有什么陷阱吗?它是线程安全的代码吗?
如何通过不同的线程获取 std::vector 数据?
解决方案
相关问题:
默认情况下 std::vector 是线程安全和并发的吗?为什么或者为什么不?.
它是线程安全的,因为您没有修改向量大小,也没有尝试在不同线程中写入相同的内存位置。
为了将来为不深入链接的任何人证明此答案:
它不是线程安全的,只是因为它们使用了
[]
运算符。它是线程安全的,因为每个线程都在显式修改内存中的不同位置。如果所有线程只使用 读取相同的位置
[]
,那将是线程安全的。如果所有线程都写入同一个位置,使用
[]
不会阻止它们相互干扰。我认为,如果这是生产代码,那么至少需要一条说明为什么这是线程安全的注释。如果有人修改此功能,不确定是否有任何编译时方法可以防止有人在脚上开枪。
在第 4 点,我们希望与此代码的未来用户沟通:
- 不,我们没有保护这个标准库容器,即使这应该是你的直觉反应,并且
- 是的,我们已经分析过了,它是安全的。
最简单的方法是在那里发表评论,但有一种说法:
编译器不会读取注释,我也不会。
-Bjarne Stroustrup
[[attributes]]
我认为应该采取某种方式来做到这一点?尽管内置插件似乎不支持任何类型的线程安全检查。
Clang 似乎提供了线程安全分析:
该分析仍在积极开发中,但它已经足够成熟,可以部署在工业环境中。
假设您实现了需要 astd::mutex
负责您的其他功能std::vector
:
std::mutex _mu;
std::vector<int> _vec GUARDED_BY(_mu);
然后您可以显式添加该NO_THREAD_SAFETY_ANALYSIS
属性以关闭此特定功能的安全检查。我认为最好将其与评论结合起来:
// I know this doesn't look safe but it is as long as
// the caller always launches it with different values of `i`
void foo(int i, std::vector<int>& vec) NO_THREAD_SAFETY_ANALYSIS;
的使用GUARDED_BY
告诉我,将来你正在考虑线程安全。的使用NO_THREAD_SAFETY_ANALYSIS
表明您已经确定该功能可以使用 - 特别是当其他修改您vector
的功能未标记时NO_THREAD_SAFETY_ANALYSIS
。
推荐阅读
- apache-spark - 将数组分解为 2 列
- google-apps-script - 如何使用脚本立即打印谷歌表格中的标记列?
- javascript - 带有 Ajax 的 Jquery 异步函数
- javascript - 在 QuillJS 中将自定义类添加到块引用
- c++ - Esp-32 从 'const char*' 到 'int' 的无效转换 [-fpermissive]
- r - 使用 Shiny 更新数据帧值并在 Shiny 会话结束后在本地环境中访问它
- c - C中gcvt()和_gcvt()的区别
- react-native - 有人可以帮助我,以便当我单击按钮时,计时器会重置吗?谢谢
- javascript - Angular 9:如何防止iOS键盘在将焦点从输入更改为表单内的另一个时消失
- c++ - 如果包含,有条件地将功能从一个标头集成到另一个标头中(这甚至有必要吗?)