c++——atomic以及内存顺序详解
简介
原子性操作库(atomic)是C++11中新增的标准库,它提供了一种线程安全的方式来访问和修改共享变量,避免了数据竞争的问题,对值进行在多线程的行为明确定义,使得不同的线程访问这个包含的值不会导致数据竞争,但是只支持基本数据类型,包括bool
、char
、short
、int
、long
、long long
等基本数据类型,以及intmax_t
、uintmax_t
、intptr_t
等扩展类型,对于用户自定义类型,需要使用 std::atomic<T*>。
template <class T> struct atomic;
示例代码
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<int> counter(0);
void incrementCounter() {
for (int i = 0; i < 100000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed);
}
}
int main() {
std::thread t1(incrementCounter);
std::thread t2(incrementCounter);
t1.join();
t2.join();
std::cout << "Final counter value: " << counter << std::endl;
return 0;
}
在这个示例中,我们创建了两个线程,每个线程都会增加计数器 100000 次。由于 counter 是一个 std::atomic,所以增加操作是线程安全的。最后,我们输出计数器的最终值,它应该是 200000
1.原子类型
2.原子类型函数
3.内存顺序
memory_order_relaxed:
这个内存顺序表示编译器可以自由地重新排序内存操作,以提高性能。不提供同步保证,但它仍然可以用于某些不需要严格同步的场景。
例如,在某些计数器或统计场景中,可以使用宽松内存序来提高性能,因为这些场景通常不需要严格的同步语义。
注意
在线程中执行多个原子操作时,会进行重排序,以提高性能,因此会产生不可预见的结果
std::atomic<bool> x, y;
void func1()//线程1执行
{
x.store(true, std::memory_order_relaxed); // 1
y.store(true, std::memory_order_relaxed); // 2
}
int main(){
std::thread t1(write_x_then_y);
t1.join();
}
在上述代码中线程执行func,指令1和指令2执行的顺序是随机的
memory_order_acquire:
获取顺序要求在当前线程中,所有后续的读操作都必须在原子操作完成后执行。这种顺序确保了当前线程对原子操作的读取操作不会被重新排序到原子操作之前,但对于写操作或其他线程中的读操作没有顺序要求。
std::atomic<bool> x, y,z;
void func1()//线程1执行
{
x.store(true, std::memory_order_relaxed); // 1//后面的不能在我前面执行,确保1第一个执行
z.store(true, std::memory_order_relaxed); // 2
y.store(true, std::memory_order_release); // 3
}
int main(){
std::thread t1(write_x_then_y);
t1.join();
}
memory_order_seq_cst:
这个内存顺序表示编译器在执行这个操作之前,必须确保之前的操作已经完成。不会对指令顺序进行优化,操作1一定会在操作2前面执行;
std::atomic<bool> x, y,z;
void func1()//线程1执行
{
x.store(true, std::memory_order_relaxed); // 1
z.store(true, std::memory_order_relaxed); // 2
y.store(true, std::memory_order_release); // 3//1,2,3按照顺序执行
}
int main(){
std::thread t1(write_x_then_y);
t1.join();
}
memory_order_release:
在这条指令执行前的对内存的读写指令都执行完毕,这条语句之后的对内存的修改指令不能超越这条指令优先执行,因为它可以确保在执行这个操作之后,之后的操作已经对其他线程可见。
std::atomic<bool> x, y,z;
void func1()//线程1执行
{
x.store(true, std::memory_order_relaxed); // 1
z.store(true, std::memory_order_relaxed); // 2
y.store(true, std::memory_order_release); // 3//前面的不能在我后面执行,1和2以及执行了
}
int main(){
std::thread t1(write_x_then_y);
t1.join();
}