c++ - C ++中多线程的安全性与速度
问题描述
如果我有一个要同时由多个线程更新的数组,那么最好/最快的方法是什么?例如,假设我有以下代码:
std::vector<float> vec;
vec.push_back(0.f);
for(int i = 0; i < 10000; i++) {
std::thread([&]{
// SAFETY CONSTRUCTS GO HERE
vec[0] += 1; // OR MAYBE HERE
// AND HERE?
});
}
// wait a little while, i.e. I was too lazy to write out joins
std::cout << vec[0];
如果我希望这是安全的并最终打印值 10000,那么最好/最快的方法是什么?
解决方案
在您给出的示例中,最好/最安全的方法是不启动线程,而只是v[0]
在循环中更新。启动和同步线程的开销可能会超过您通过并行执行某些操作所获得的任何好处。
v
是一个非原子对象 ( std::vector<float>
),v[0]
实际上是一个函数调用。此类对象及其非静态成员函数无法保护自己免受多个线程的并发访问。要从多个线程中使用它们,必须同步v
(and ) 的每次直接使用。v[0]
通常,通过同步对由多个线程更新和访问的任何变量(或更一般地,内存)的访问来实现涉及并发执行线程的安全性。
如果使用互斥锁,这通常意味着所有访问共享数据的线程必须首先获取互斥锁,对共享变量进行操作(例如 update v[0]
),然后释放互斥锁。如果一个线程没有抓取(或抓取然后释放)互斥锁,那么它所做的所有操作都不能触及共享变量。
如果您希望通过线程来提高性能,则需要在每个线程中完成大量工作,而无需对共享变量进行任何访问。由于可以同时执行部分工作,因此该工作可能会在更少的总运行时间内执行。为了代表性能优势,收益(例如通过同时执行大量操作)需要超过成本(启动线程,同步访问由多个线程访问的任何数据)。
在与您显示的代码类似的任何事情中,这都是极不可能的。
关键是,当线程共享任何数据时,速度和安全性之间总是存在权衡。安全需要同步更新共享变量 - 无一例外。性能增益通常来自不需要同步的事物(即不访问线程之间共享的变量)并且可以并行执行。
推荐阅读
- c# - 实体框架自动化迁移
- jquery - 如何在此代码中添加动画(慢速滚动效果)
- keras - 我在 colab google 工具中遇到错误,我该如何解决这个错误?
- javascript - 同步处理嵌套数组
- r - 为什么 ggplot 会删除我 99% 的观察结果?
- ios - 如果不重新启动应用程序,iOS 故事板本地化将无法正常工作
- javascript - Autodesk Forge 设计自动化/模型衍生 API - 查看器缓存 svf 文件
- python - 如何按行和列索引将元素插入 Numpy 矩阵
- php - 我可以通过路由 laravel 传递多维数组吗?
- javascript - 需要帮助在 Javascript 中创建对象数组