推荐答案
// www.javascriptcn.com code example
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<int> counter(0);
void increment_counter() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed);
}
}
int main() {
std::thread t1(increment_counter);
std::thread t2(increment_counter);
t1.join();
t2.join();
std::cout << "Counter value: " << counter.load() << std::endl;
return 0;
}本题详细解读
std::atomic 概述
std::atomic 是 C++11 引入的一个模板类,用于在多线程环境中提供原子操作。原子操作是指不会被线程调度机制打断的操作,即该操作一旦开始,就会一直运行到结束,中间不会有任何上下文切换。
主要成员函数
load(): 读取原子变量的值。int value = counter.load(std::memory_order_relaxed);
store(): 设置原子变量的值。counter.store(10, std::memory_order_relaxed);
fetch_add(): 原子地将一个值加到原子变量上,并返回之前的值。int previous_value = counter.fetch_add(1, std::memory_order_relaxed);
fetch_sub(): 原子地将一个值从原子变量中减去,并返回之前的值。int previous_value = counter.fetch_sub(1, std::memory_order_relaxed);
exchange(): 原子地将原子变量的值替换为指定值,并返回之前的值。int previous_value = counter.exchange(5, std::memory_order_relaxed);
compare_exchange_weak()和compare_exchange_strong(): 比较并交换操作,通常用于实现无锁数据结构。bool success = counter.compare_exchange_weak(expected, desired, std::memory_order_relaxed);
内存顺序
std::atomic 操作可以指定内存顺序(Memory Order),以控制操作的可见性和顺序性。常见的内存顺序包括:
std::memory_order_relaxed: 最宽松的内存顺序,只保证原子性。std::memory_order_acquire: 保证该操作之后的读操作不会被重排序到该操作之前。std::memory_order_release: 保证该操作之前的写操作不会被重排序到该操作之后。std::memory_order_seq_cst: 最严格的内存顺序,保证所有操作的全局顺序一致性。
示例代码解析
在示例代码中,std::atomic<int> counter(0); 定义了一个原子整数 counter,初始值为 0。increment_counter 函数通过 fetch_add 原子地将 counter 增加 1000 次。两个线程 t1 和 t2 同时执行 increment_counter 函数,最终 counter 的值应为 2000。
注意事项
std::atomic适用于简单的数据类型(如int,bool,pointer等)。对于复杂类型,可能需要使用std::mutex或其他同步机制。- 使用
std::atomic时,应谨慎选择内存顺序,以确保程序的正确性和性能。
通过 std::atomic,C++ 程序员可以方便地在多线程环境中实现无锁编程,从而提高程序的并发性能。