如何正确地增加c++ 11的std::atomic
How can I properly increase C++11 std::atomic?
我是多线程编程的新手,我在c++ 11中找到了std::atomic
。
所以,我试着算出原子操作需要多少时间。
我试过这个代码:
using namespace std;
using namespace std::chrono;
constexpr int NUM_THREADS = 8;
constexpr int LIMIT = 100000;
atomic<int> sum = 0;
void foo(int idx) {
while (true) {
if (sum.load() >= LIMIT) {
return;
}
sum.fetch_add(1);
}
}
with main
:
int main(void) {
thread threads[NUM_THREADS];
auto start = high_resolution_clock::now();
for (int i = 0; i < NUM_THREADS; i++) {
threads[i] = thread(&foo, i);
}
for (int i = 0; i < NUM_THREADS; i++) {
threads[i].join();
}
auto du = high_resolution_clock::now() - start;
cout << "computing timett" << duration_cast<milliseconds>(du).count() << "ms" << endl;
cout << "number of threadt" << NUM_THREADS << endl;
cout << "sumttt" << sum << endl;
return 0;
}
但sum
并不总是与LIMIT
相同。
据我所知,原子操作在被调用时是线程安全的。所以,是的,我认为我的代码是错误的,但是我不知道如何使它正常工作。
我怎么能得到一个正确的结果与main
?
(好吧,这个版本将使sum
和LIMIT
相等,但我认为这不是一个好方法…)
void foo(int idx) {
for (int i = 0; i < LIMIT / NUM_THREADS; i++) {
sum.fetch_add(1);
}
}
正如在评论中所说,您的问题是变量在加载它和增加它的时间之间由另一个线程更改。
你可以改变你的循环,例如像这样来修复它:
while (true) {
auto current = sum.load();
if (current >= LIMIT) {
return;
}
auto next = current + 1;
sum.compare_exchange_strong(current, next));
}
operator++
是原子上的原子类型,所以您需要做的就是:
void foo(int idx) {
while (true) {
if (sum++ >= LIMIT) {
return;
}
}
}
一旦其中一个线程将sum
增加到LIMIT
,其他线程也将看到该值大于或等于LIMIT
并返回。这里有一个风险:如果线程数大于std::numeric_limits<int>::max() - LIMIT
,那么后面的一个线程将使sum
超过int
的最大值。只要LIMIT
是明智的
相关文章:
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 在 lambda 表达式中使用 std::atomic
- C++std::atomic在程序员级别保证了什么
- 如果在 2 个线程中使用,是否值得将size_t声明为 std::atomic?
- 在 C++20 之前和之后初始化 std::atomic
- std::atomic 和 std::mutex 的相对性能
- 简单使用 std::atomic 在两个线程之间共享数据
- Port pthread_cond_broadcast to std::atomic
- std::atomic中的任何内容都是免费等待的
- 为什么 std::atomic 构造函数在 C++14 和 C++17 中的行为不同
- std::atomic是如何实现的
- 使用 std::atomic 标志和 std::condition_variable 在工作线程上等待
- 为什么std::atomic的默认构造函数不默认初始化底层存储值
- 读取互斥对象范围之外的volatile变量,而不是std::atomic
- 为什么std::atomic中的所有成员函数都同时出现在有volatile和没有volatile的情况下
- 访问共享内存而不使用易失性、std::atomic、信号量、互斥锁和自旋锁
- 两个不同的进程,在同一地址上有 2 个 std::atomic 变量?
- 原子读取,然后使用 std::atomic 写入
- std::atomic::fetch_add是x86-64上的串行化操作
- 实际上,C++11 中 std::atomic 的内存占用量是多少?