简介
- C++
标准库
C++ 标准库 详解
<atomic>
是 C++ 标准库中提供的用于原子操作的头文件,它提供了一组工具和类型,用于在多线程环境中执行原子操作。原子操作是指在执行过程中不会被中断的操作,它们能够确保多个线程同时访问共享数据时不会发生竞态条件(race condition)。
以下是 <atomic>
头文件中最常用的类和函数:
原子类型
- std::atomic<T>: 这是模板类,提供了对类型 T 的原子访问。可以使用不同的基本数据类型(如整数、指针等)来实例化它。
原子操作函数
store()
: 将值存储到原子对象中。load()
: 从原子对象中加载值。exchange()
: 将新值存储到原子对象中,并返回先前的值。compare_exchange_weak()
和compare_exchange_strong()
: 比较原子对象的值与预期值,如果相等则修改。compare_exchange_weak()
可能会在比较失败时返回false
,而compare_exchange_strong()
则保证了强一致性。fetch_add()
,fetch_sub()
,fetch_and()
,fetch_or()
,fetch_xor()
: 执行原子的加法、减法、与操作、或操作和异或操作,并返回操作之前的值。
其他重要函数和特性
is_lock_free()
: 检查给定类型的原子操作是否是无锁的,即是否可以在特定平台上以原子方式执行。- Memory Order(内存顺序):这些是在原子操作中指定的参数,用于控制原子操作的顺序和可见性。
memory_order_relaxed
: 最轻量级的内存顺序,没有顺序约束。memory_order_acquire
,memory_order_release
: 分别用于读操作和写操作的同步。memory_order_consume
: 用于依赖关系。memory_order_seq_cst
: 最严格的内存顺序,提供全序保证。
示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> atomic_counter(0);
void increment_counter() {
for (int i = 0; i < 1000; ++i) {
atomic_counter.fetch_add(1, std::memory_order_relaxed);
}
}
int main() {
std::thread thread1(increment_counter);
std::thread thread2(increment_counter);
thread1.join();
thread2.join();
std::cout << "Final counter value: " << atomic_counter.load() << std::endl;
return 0;
}
这是一个简单的示例,展示了如何使用 <atomic>
来确保在多线程环境中对共享变量进行原子操作。在这个例子中,两个线程分别调用 increment_counter()
函数来增加 atomic_counter
的值,最终输出其最终的值。
请注意,在使用原子操作时要小心避免出现数据竞争和不正确的同步问题。原子操作能够提供基本的线程安全保证,但仍需谨慎设计代码以避免更复杂的并发问题。
C++ 标准库 常用类和函数
在 C++ 标准库中的 <atomic>
头文件中,常用的类和函数如下:
常用类:
- std::atomic<T>:表示一个原子类型,用于执行对类型
T
的原子操作。store(val, order)
: 将值val
存储到原子对象中,使用指定的内存顺序order
。load(order)
: 从原子对象中加载值,使用指定的内存顺序order
。exchange(val, order)
: 将新值val
存储到原子对象中,并返回先前的值,使用指定的内存顺序order
。compare_exchange_weak(expected, val, order_success, order_failure)
: 如果原子对象的值等于expected
,则将其设置为val
,并返回true
;否则,将expected
更新为原子对象的当前值,并返回false
。该操作使用order_success
和order_failure
指定的内存顺序。fetch_add(val, order)
,fetch_sub(val, order)
,fetch_and(val, order)
,fetch_or(val, order)
,fetch_xor(val, order)
: 执行原子的加法、减法、与操作、或操作和异或操作,并返回操作之前的值,使用指定的内存顺序order
。
常用函数:
- std::atomic_thread_fence(order):在当前线程执行内存屏障(memory fence),强制按照指定的内存顺序
order
来排序内存访问操作。 - std::atomic_signal_fence(order):在当前线程执行信号屏障(signal fence),强制按照指定的内存顺序
order
来排序内存访问操作,但不影响线程间的同步。 - std::atomic_is_lock_free(&obj):检查给定的原子对象
obj
是否是无锁的,返回true
表示原子类型在特定平台上支持无锁操作。
内存顺序(Memory Order):
std::memory_order_relaxed
:最轻量级的内存顺序,没有顺序约束。std::memory_order_acquire
:用于读取操作,确保在这个操作之后的读取操作都不会被重新排序到这个操作之前。std::memory_order_release
:用于写入操作,确保在这个操作之前的写入操作都不会被重新排序到这个操作之后。std::memory_order_acq_rel
:同时包括acquire
和release
的特性。std::memory_order_seq_cst
:最严格的内存顺序,提供全序保证。
这些类和函数提供了一套原子操作的工具,使得在多线程环境中对共享数据进行操作时更加安全和可靠。在使用时,需要注意内存顺序和操作的原子性,以确保正确的并发行为。
std::atomic
std::atomic
是 C++ 标准库 <atomic>
中定义的模板类,用于执行原子操作,提供了多线程环境下对共享变量的安全访问。std::atomic
类型的变量可以保证其操作的原子性,即对它们的操作不会被中断。
主要特性和操作:
-
原子操作:
std::atomic
类型的变量支持多种原子操作,包括读取、写入和各种算术和逻辑操作。这些操作保证在多线程环境中的原子性,不会被其他线程的操作中断。 -
内存顺序(Memory Order):原子操作可以指定内存顺序,即操作在多线程间的执行顺序,包括
memory_order_relaxed
、memory_order_acquire
、memory_order_release
等。 -
支持的操作:
std::atomic
类型支持各种操作,如加载(load)、存储(store)、交换(exchange)、比较交换(compare_exchange_strong/compare_exchange_weak)等。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> counter(0);
void incrementCounter() {
for (int i = 0; i < 10000; ++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 << "Counter value: " << counter << std::endl; // 输出计数器的值
return 0;
}
在上述示例中,std::atomic<int>
类型的 counter
变量用于在两个线程中增加一个计数器的值。fetch_add()
函数用于原子性地增加计数器的值,保证了多线程环境下的安全访问。最终输出的 counter
值应该是 20000
,因为两个线程各自增加了 10000
次。
std::atomic::store()
std::atomic::store()
是 std::atomic
类中的一个成员函数,用于将指定的值存储到原子对象中。这个函数是用于原子性地将新值存储到 std::atomic
对象中的方法之一。
1
void store( T value, std::memory_order order = std::memory_order_seq_cst ) noexcept;
value
是要存储到原子对象中的新值。order
是可选的参数,表示存储操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(0);
atomic_value.store(42); // 将值 42 存储到 atomic_value 中,默认使用 std::memory_order_seq_cst
std::cout << "Value stored: " << atomic_value.load() << std::endl; // 输出存储后的值
return 0;
}
这个例子中,store()
将值 42 存储到 atomic_value
中,并通过 load()
方法加载并打印存储后的值。这些操作都是原子的,保证在多线程环境中的线程安全性。
std::atomic::load()
std::atomic::load()
是 std::atomic
类的成员函数,用于从原子对象中加载值并返回该值。它是用于原子地获取 std::atomic
对象的值的方法之一。
1
T load(std::memory_order order = std::memory_order_seq_cst) const noexcept;
order
是可选的参数,表示加载操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(42);
int loaded_value = atomic_value.load(); // 从 atomic_value 中加载值,默认使用 std::memory_order_seq_cst
std::cout << "Value loaded: " << loaded_value << std::endl; // 输出加载的值
return 0;
}
在这个例子中,load()
方法从 atomic_value
中加载其当前的值,并将其赋给 loaded_value
变量。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::exchange()
std::atomic::exchange()
是 std::atomic
类的成员函数,用于将新值存储到原子对象中,并返回先前的值。这个函数允许原子地交换原子对象的值。
1
T exchange(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept;
desired
是要存储到原子对象中的新值。order
是可选的参数,表示交换操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(42);
int old_value = atomic_value.exchange(100); // 将值 100 存储到 atomic_value 中,并返回先前的值,默认使用 std::memory_order_seq_cst
std::cout << "Old value exchanged: " << old_value << std::endl; // 输出交换前的值
std::cout << "Current value: " << atomic_value.load() << std::endl; // 输出当前值
return 0;
}
在这个例子中,exchange()
方法将值 100 存储到 atomic_value
中,并将先前的值(42)返回并存储在 old_value
中。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::compare_exchange_weak()
std::atomic::compare_exchange_weak()
是 std::atomic
类的成员函数,用于原子地比较原子对象的值与预期值,如果相等,则修改为新值。它是一种 CAS(比较并交换)操作的弱保证版本,可能在比较失败时返回 false
,但不会引发重试。
1
2
3
bool compare_exchange_weak(T& expected, T desired,
std::memory_order success = std::memory_order_seq_cst,
std::memory_order failure = std::memory_order_seq_cst) noexcept;
expected
是期望的值,如果原子对象的值与expected
相等,则修改为desired
。desired
是要存储到原子对象中的新值。success
是可选参数,表示成功时使用的内存顺序,默认值是std::memory_order_seq_cst
。failure
是可选参数,表示比较失败时使用的内存顺序,默认值也是std::memory_order_seq_cst
。
该函数将比较预期值(expected
)和原子对象的当前值,如果相等,则将原子对象的值设置为 desired
,并返回 true
;否则,将 expected
更新为原子对象的当前值,并返回 false
。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(42);
int expected = 42;
int desired = 100;
bool success = atomic_value.compare_exchange_weak(expected, desired); // 比较预期值与原子对象的值,若相等则修改为新值
if (success) {
std::cout << "Value exchanged successfully!" << std::endl;
} else {
std::cout << "Value not exchanged. Expected: " << expected << ", Actual: " << atomic_value.load() << std::endl;
}
return 0;
}
在这个例子中,compare_exchange_weak()
将比较 atomic_value
和 expected
,若相等,则将其修改为 desired
。成功时返回 true
,并输出成功的消息,否则返回 false
,并输出原子对象的当前值和预期值。
std::atomic::fetch_add()
std::atomic::fetch_add()
是 std::atomic
类的成员函数,用于执行原子的加法操作,并返回操作之前的值。它是一种原子操作,用于对原子对象的值进行增加操作。
1
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
arg
是要增加到原子对象中的值。order
是可选参数,表示操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
该函数将原子对象的值增加 arg
,并返回增加前的值。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(10);
int previous_value = atomic_value.fetch_add(5); // 将值 5 加到 atomic_value 中,并返回增加前的值,默认使用 std::memory_order_seq_cst
std::cout << "Previous value: " << previous_value << std::endl; // 输出增加前的值
std::cout << "Current value: " << atomic_value.load() << std::endl; // 输出当前值
return 0;
}
在这个例子中,fetch_add()
方法将值 5 加到 atomic_value
中,并返回增加前的值。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::fetch_sub()
std::atomic::fetch_sub()
是 std::atomic
类的成员函数,用于执行原子的减法操作,并返回操作之前的值。它是一种原子操作,用于对原子对象的值进行减少操作。
1
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
arg
是要减少的值,会从原子对象中减去这个值。order
是可选参数,表示操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
该函数将原子对象的值减少 arg
,并返回减少前的值。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(20);
int previous_value = atomic_value.fetch_sub(7); // 从 atomic_value 中减去值 7,并返回减少前的值,默认使用 std::memory_order_seq_cst
std::cout << "Previous value: " << previous_value << std::endl; // 输出减少前的值
std::cout << "Current value: " << atomic_value.load() << std::endl; // 输出当前值
return 0;
}
在这个例子中,fetch_sub()
方法将值 7 从 atomic_value
中减去,并返回减少前的值。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::fetch_add()
std::atomic::fetch_and()
是 std::atomic
类的成员函数,用于执行原子的按位与(AND)操作,并返回操作之前的值。它是一种原子操作,用于对原子对象的值进行按位与操作。
1
T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
arg
是用于按位与运算的操作数,会与原子对象的值进行按位与操作。order
是可选参数,表示操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
该函数将原子对象的值与 arg
进行按位与运算,并返回按位与运算前的原子对象的值。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(0b1100); // 值为 12 (二进制 1100)
int previous_value = atomic_value.fetch_and(0b1010); // 对 atomic_value 进行按位与操作,并返回按位与前的值,默认使用 std::memory_order_seq_cst
std::cout << "Previous value: " << previous_value << std::endl; // 输出按位与前的值
std::cout << "Current value: " << atomic_value.load() << std::endl; // 输出当前值
return 0;
}
在这个例子中,fetch_and()
方法将 atomic_value
的值与 0b1010 进行按位与操作,并返回按位与操作前的值。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::fetch_or()
std::atomic::fetch_or()
是 std::atomic
类的成员函数,用于执行原子的按位或(OR)操作,并返回操作之前的值。它是一种原子操作,用于对原子对象的值进行按位或操作。
1
T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
arg
是用于按位或运算的操作数,会与原子对象的值进行按位或操作。order
是可选参数,表示操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
该函数将原子对象的值与 arg
进行按位或运算,并返回按位或运算前的原子对象的值。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(0b1100); // 值为 12 (二进制 1100)
int previous_value = atomic_value.fetch_or(0b1010); // 对 atomic_value 进行按位或操作,并返回按位或前的值,默认使用 std::memory_order_seq_cst
std::cout << "Previous value: " << previous_value << std::endl; // 输出按位或前的值
std::cout << "Current value: " << atomic_value.load() << std::endl; // 输出当前值
return 0;
}
在这个例子中,fetch_or()
方法将 atomic_value
的值与 0b1010 进行按位或操作,并返回按位或操作前的值。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::fetch_xor()
std::atomic::fetch_xor()
是 std::atomic
类的成员函数,用于执行原子的按位异或(XOR)操作,并返回操作之前的值。它是一种原子操作,用于对原子对象的值进行按位异或操作。
1
T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
arg
是用于按位异或运算的操作数,会与原子对象的值进行按位异或操作。order
是可选参数,表示操作所使用的内存顺序,默认值是std::memory_order_seq_cst
,即最严格的顺序,提供全序保证。
该函数将原子对象的值与 arg
进行按位异或运算,并返回按位异或运算前的原子对象的值。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(0b1100); // 值为 12 (二进制 1100)
int previous_value = atomic_value.fetch_xor(0b1010); // 对 atomic_value 进行按位异或操作,并返回按位异或前的值,默认使用 std::memory_order_seq_cst
std::cout << "Previous value: " << previous_value << std::endl; // 输出按位异或前的值
std::cout << "Current value: " << atomic_value.load() << std::endl; // 输出当前值
return 0;
}
在这个例子中,fetch_xor()
方法将 atomic_value
的值与 0b1010 进行按位异或操作,并返回按位异或操作前的值。这个操作是原子的,确保在多线程环境中的线程安全性。
std::atomic::is_lock_free()
std::atomic::is_lock_free()
是 std::atomic
类的成员函数,用于检查特定类型的原子操作是否是无锁(lock-free)的。这个函数返回一个布尔值,表示给定类型的原子操作是否可以在特定平台上以无锁方式执行。
1
static constexpr bool is_lock_free() noexcept;
这个函数是一个静态成员函数,可以在实例化 std::atomic
类之前使用。它在编译时确定,用于检查给定类型的原子操作是否可以在当前平台上以无锁方式执行。如果返回 true
,表示该类型的原子操作在该平台上是无锁的;如果返回 false
,则表示不是无锁的。
示例用法:
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <atomic>
int main() {
std::cout << "Atomic int is lock-free: " << std::atomic<int>::is_lock_free() << std::endl;
std::cout << "Atomic double is lock-free: " << std::atomic<double>::is_lock_free() << std::endl;
return 0;
}
这个例子中,is_lock_free()
分别检查 std::atomic<int>
和 std::atomic<double>
是否是无锁的,并输出结果。这个函数对于确定特定类型的原子操作在给定平台上是否无锁非常有用。
std::atomic::memory_order_relaxed()
在C++中,std::atomic
的成员函数 memory_order_relaxed
是一个静态成员函数,它用于提供一个标志位(枚举类型)std::memory_order_relaxed
,用于指示最轻松的内存顺序,它表示不对原子操作的顺序做出任何约束。
std::memory_order_relaxed
并不是 std::atomic
类的函数,而是用于指定原子操作内存顺序的枚举类型。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <atomic>
int main() {
std::atomic<int> atomic_value(0);
atomic_value.store(42, std::memory_order_relaxed); // 使用 relaxed 内存顺序进行存储操作
int loaded_value = atomic_value.load(std::memory_order_relaxed); // 使用 relaxed 内存顺序进行加载操作
std::cout << "Value stored and loaded with relaxed order: " << loaded_value << std::endl;
return 0;
}
在这个示例中,std::memory_order_relaxed
被用作 store()
和 load()
方法的参数,指定了这些原子操作的内存顺序是最轻松的,没有特定的顺序约束。
std::memory_order_acquire
std::memory_order_acquire
是 C++ 标准库 <atomic>
头文件中定义的枚举常量之一,用于指定原子操作中的内存顺序,特别是用于读取操作的同步方式。
这个枚举类型属于 std::memory_order
枚举类,表示一种内存顺序,用于指定在某个原子操作中读取的同步方式。具体地说,std::memory_order_acquire
用于确保在当前读取操作之后,后续的读取操作不会被重排序到前面。
在实际编程中,可以将 std::memory_order_acquire
作为参数传递给原子操作的函数,例如 load()
函数,以指定该操作的内存顺序。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> shared_data(0);
std::atomic<bool> ready(false);
void writer() {
shared_data.store(42, std::memory_order_relaxed);
ready.store(true, std::memory_order_release);
}
void reader() {
while (!ready.load(std::memory_order_acquire)) {
std::this_thread::yield(); // 等待写者完成
}
std::cout << "Value read: " << shared_data.load(std::memory_order_relaxed) << std::endl;
}
int main() {
std::thread writer_thread(writer);
std::thread reader_thread(reader);
writer_thread.join();
reader_thread.join();
return 0;
}
在这个示例中,std::memory_order_acquire
被用作 load()
和 store()
方法的参数,确保在读取 shared_data
和设置 ready
的值时使用了正确的内存顺序,以确保线程间的同步。
std::memory_order_release
std::memory_order_release
是 C++ 标准库 <atomic>
头文件中定义的枚举常量之一,用于指定原子操作中的内存顺序,特别是用于写入操作的同步方式。
这个枚举类型属于 std::memory_order
枚举类,表示一种内存顺序,用于指定在某个原子操作中写入的同步方式。具体地说,std::memory_order_release
用于确保在当前写入操作之前,前面的写入操作不会被重排序到后面。
在实际编程中,可以将 std::memory_order_release
作为参数传递给原子操作的函数,例如 store()
函数,以指定该操作的内存顺序。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> shared_data(0);
std::atomic<bool> ready(false);
void writer() {
shared_data.store(42, std::memory_order_relaxed);
ready.store(true, std::memory_order_release);
}
void reader() {
while (!ready.load(std::memory_order_acquire)) {
std::this_thread::yield(); // 等待写者完成
}
std::cout << "Value read: " << shared_data.load(std::memory_order_relaxed) << std::endl;
}
int main() {
std::thread writer_thread(writer);
std::thread reader_thread(reader);
writer_thread.join();
reader_thread.join();
return 0;
}
在这个示例中,std::memory_order_release
被用作 store()
和 load()
方法的参数,确保在写入 shared_data
和读取 ready
的值时使用了正确的内存顺序,以确保线程间的同步。
std::memory_order_seq_cst
std::memory_order_seq_cst
是 C++ 标准库 <atomic>
头文件中定义的枚举常量之一,用于指定原子操作中的内存顺序。
这个枚举类型属于 std::memory_order
枚举类,表示顺序一致性内存顺序。具体地说,std::memory_order_seq_cst
表示全序(Total Ordering)保证,即对于所有线程来说,原子操作的执行顺序与其在代码中的顺序一致。
在实际编程中,std::memory_order_seq_cst
通常是默认的内存顺序,并被用作原子操作的函数参数,例如 load()
、store()
、exchange()
等,以指定原子操作的内存顺序。
示例用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> shared_data(0);
std::atomic<bool> ready(false);
void writer() {
shared_data.store(42, std::memory_order_seq_cst); // 使用 std::memory_order_seq_cst 内存顺序进行存储操作
ready.store(true, std::memory_order_seq_cst); // 使用 std::memory_order_seq_cst 内存顺序进行存储操作
}
void reader() {
while (!ready.load(std::memory_order_seq_cst)) { // 使用 std::memory_order_seq_cst 内存顺序进行加载操作
std::this_thread::yield(); // 等待写者完成
}
std::cout << "Value read: " << shared_data.load(std::memory_order_seq_cst) << std::endl; // 使用 std::memory_order_seq_cst 内存顺序进行加载操作
}
int main() {
std::thread writer_thread(writer);
std::thread reader_thread(reader);
writer_thread.join();
reader_thread.join();
return 0;
}
在这个示例中,std::memory_order_seq_cst
被用作 load()
、store()
方法的参数,确保在读取 shared_data
和设置 ready
的值时使用了顺序一致性的内存顺序,以确保线程间的同步。
C++ std::atomic::compare_exchange_strong() 函数 详解
std::atomic::compare_exchange_strong()
是 C++ 标准库中 std::atomic
类提供的一个成员函数,用于原子比较和交换操作。它允许在多线程环境中安全地执行原子操作,确保在没有其他线程干扰的情况下执行比较和交换。
以下是该函数的详细解释:
函数签名:
1
bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order_seq_cst) noexcept;
参数:
-
expected
:传入一个引用,表示当前的期望值。如果当前的值等于期望值,比较和交换操作将成功,并将desired
的值写入std::atomic
对象;否则,expected
保持不变。 -
desired
:传入一个新值,如果当前的值等于expected
,则用desired
替换当前值。 -
order
:传入一个可选参数,表示内存顺序(memory order)的类型,默认是memory_order_seq_cst
。内存顺序用于控制不同线程之间的操作顺序,可以选择不同的内存顺序来权衡性能和一致性。
返回值:
-
如果比较和交换成功(当前值等于期望值),则返回
true
,并将desired
的值写入std::atomic
对象。 -
如果比较和交换失败(当前值不等于期望值),则返回
false
,并将expected
的值更新为当前的实际值。
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> data(0);
int main() {
int expected = 0;
int desired = 1;
if (data.compare_exchange_strong(expected, desired)) {
std::cout << "Exchange successful. New value: " << data.load() << std::endl;
} else {
std::cout << "Exchange failed. Current value: " << data.load() << std::endl;
}
return 0;
}
在这个例子中,如果 data
的当前值等于 expected
(初始值为0),则将 desired
(值为1)写入 data
,并输出成功的消息。否则,输出失败的消息。
请注意,compare_exchange_strong()
函数是一个原子操作,因此可以在多线程环境中安全使用,确保在没有竞态条件的情况下执行比较和交换。
C++ std::atomic::compare_exchange_strong() 函数对enum class类型怎么处理
std::atomic::compare_exchange_strong()
函数对于 enum class
类型的处理与其他类型类似。这个函数用于原子地比较并交换值,确保在多线程环境中执行这个操作是安全的。
以下是 compare_exchange_strong()
函数的一般形式:
1
bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order_seq_cst) noexcept;
其中,T
是 std::atomic
包装的类型。对于 enum class
类型,你可以使用该函数进行原子比较和交换。
假设你有一个 enum class
类型如下:
1
enum class MyEnum { Value1, Value2, Value3 };
你可以使用 std::atomic
包装这个类型,并使用 compare_exchange_strong()
函数进行原子比较和交换:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <atomic>
int main() {
std::atomic<MyEnum> atomicEnum(MyEnum::Value1);
MyEnum expected = MyEnum::Value1;
MyEnum desired = MyEnum::Value2;
bool success = atomicEnum.compare_exchange_strong(expected, desired);
if (success) {
std::cout << "Exchange successful. New value: " << static_cast<int>(desired) << std::endl;
} else {
std::cout << "Exchange failed. Current value: " << static_cast<int>(atomicEnum.load()) << std::endl;
}
return 0;
}
在这个例子中,compare_exchange_strong()
函数将 atomicEnum
的当前值与 expected
进行比较。如果它们相等,将 desired
值写入 atomicEnum
中,并返回 true
表示交换成功。否则,返回 false
表示交换失败,并将 expected
更新为当前的实际值。
需要注意的是,由于 enum class
类型的底层类型是整数,所以在打印时需要使用 static_cast<int>
进行强制转换。
总体来说,compare_exchange_strong()
函数对 enum class
类型的处理方式与其他类型相似,提供了一种在多线程环境中执行原子比较和交换的安全手段。