Rust原子枚举库atomic_enum的使用:高效线程安全枚举操作与并发控制
atomic_enum
一个用于为C风格枚举创建原子包装器的属性。
在内部,生成的包装器使用AtomicUsize
来存储值。
原子操作具有与AtomicUsize
的等效操作相同的语义。
示例
# use atomic_enum::atomic_enum;
# use std::sync::atomic::Ordering;
#[atomic_enum]
#[derive(PartialEq)]
enum CatState {
Dead = 0,
BothDeadAndAlive,
Alive,
}
let state = AtomicCatState::new(CatState::Dead);
state.store(CatState::Alive, Ordering::Relaxed);
assert_eq!(state.load(Ordering::Relaxed), CatState::Alive);
此属性不使用或生成任何不安全代码。
该crate可以在#[no_std]
环境中使用。
维护说明
此crate是被动维护的。
完整示例代码
use atomic_enum::atomic_enum;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::thread;
// 定义一个原子枚举
#[atomic_enum]
#[derive(PartialEq, Debug)]
enum ThreadState {
Idle = 0,
Working,
Finished,
}
fn main() {
// 创建原子枚举实例
let state = Arc::new(AtomicThreadState::new(ThreadState::Idle));
// 克隆Arc用于线程
let state_clone = Arc::clone(&state);
// 创建工作线程
let handle = thread::spawn(move || {
// 将状态设置为Working
state_clone.store(ThreadState::Working, Ordering::SeqCst);
println!("线程开始工作...");
// 模拟一些工作
thread::sleep(std::time::Duration::from_secs(2));
// 将状态设置为Finished
state_clone.store(ThreadState::Finished, Ordering::SeqCst);
println!("线程完成工作");
});
// 主线程监控状态变化
while state.load(Ordering::SeqCst) != ThreadState::Finished {
let current_state = state.load(Ordering::SeqCst);
match current_state {
ThreadState::Idle => println!("主线程检测到状态: Idle"),
ThreadState::Working => println!("主线程检测到状态: Working"),
ThreadState::Finished => break,
}
thread::sleep(std::time::Duration::from_millis(500));
}
// 等待工作线程完成
handle.join().unwrap();
// 最终状态确认
assert_eq!(state.load(Ordering::SeqCst), ThreadState::Finished);
println!("所有操作完成,最终状态: {:?}", state.load(Ordering::SeqCst));
}
1 回复
Rust原子枚举库atomic_enum的使用指南
介绍
atomic_enum是一个专门为Rust设计的原子枚举库,它提供了线程安全的枚举操作能力。通过使用原子操作和内存排序保证,该库能够在多线程环境中安全地操作枚举值,避免了传统互斥锁带来的性能开销。
主要特性
- 线程安全的枚举值读写操作
- 支持多种内存排序策略
- 零额外内存开销(与标准枚举大小相同)
- 无锁并发控制
- 与标准库原子类型相似的API设计
使用方法
安装
在Cargo.toml中添加依赖:
[dependencies]
atomic_enum = "0.2"
基本使用示例
use atomic_enum::atomic_enum;
use std::sync::atomic::Ordering;
// 定义原子枚举
#[atomic_enum]
#[derive(PartialEq)]
enum State {
Idle,
Running,
Stopped,
}
fn main() {
// 创建原子枚举实例
let state = AtomicState::new(State::Idle);
// 存储枚举值
state.store(State::Running, Ordering::SeqCst);
// 加载当前值
let current = state.load(Ordering::SeqCst);
println!("Current state: {:?}", current);
// 比较并交换操作
let result = state.compare_exchange(
State::Running,
State::Stopped,
Ordering::SeqCst,
Ordering::Relaxed
);
match result {
Ok(_) => println!("状态成功从Running切换到Stopped"),
Err(actual) => println!("状态切换失败,当前状态为: {:?}", actual),
}
}
多线程示例
use atomic_enum::atomic_enum;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
#[atomic_enum]
#[derive(PartialEq, Debug)]
enum WorkerState {
Waiting,
Processing,
Completed,
Error,
}
fn main() {
let state = AtomicWorkerState::new(WorkerState::Waiting);
// 创建工作线程
let handle = thread::spawn({
let state = state.clone();
move || {
// 模拟工作
state.store(WorkerState::Processing, Ordering::Release);
thread::sleep(Duration::from_millis(100));
// 随机选择完成或错误状态
if rand::random() {
state.store(WorkerState::Completed, Ordering::Release);
} else {
state.store(WorkerState::Error, Ordering::Release);
}
}
});
// 主线程监控状态
while state.load(Ordering::Acquire) == WorkerState::Processing {
println!("工作仍在进行中...");
thread::sleep(Duration::from_millis(20));
}
let final_state = state.load(Ordering::Acquire);
println!("最终状态: {:?}", final_state);
handle.join().unwrap();
}
内存排序选项
atomic_enum支持标准的内存排序选项:
Ordering::Relaxed
- 最弱的内存排序保证Ordering::Acquire
- 加载操作的获取语义Ordering::Release
- 存储操作的释放语义Ordering::AcqRel
- 获取-释放语义Ordering::SeqCst
- 顺序一致性(最强保证)
完整示例demo
use atomic_enum::atomic_enum;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use rand::Rng;
// 定义任务状态枚举
#[atomic_enum]
#[derive(PartialEq, Debug, Clone, Copy)]
enum TaskStatus {
Pending, // 等待中
Processing, // 处理中
Success, // 成功
Failed, // 失败
Cancelled, // 已取消
}
fn main() {
// 创建原子枚举实例,初始状态为Pending
let status = AtomicTaskStatus::new(TaskStatus::Pending);
println!("任务启动,初始状态: {:?}", status.load(Ordering::SeqCst));
// 创建多个工作线程
let mut handles = vec![];
for i in 0..3 {
let status_clone = status.clone();
let handle = thread::spawn(move || {
// 尝试将状态从Pending改为Processing
let result = status_clone.compare_exchange(
TaskStatus::Pending,
TaskStatus::Processing,
Ordering::SeqCst,
Ordering::Relaxed
);
match result {
Ok(_) => {
println!("线程{}成功获取任务", i);
// 模拟任务处理时间
thread::sleep(Duration::from_millis(50 + i * 20));
// 随机决定任务结果
let mut rng = rand::thread_rng();
let success: bool = rng.gen();
if success {
status_clone.store(TaskStatus::Success, Ordering::Release);
println!("线程{}任务执行成功", i);
} else {
status_clone.store(TaskStatus::Failed, Ordering::Release);
println!("线程{}任务执行失败", i);
}
}
Err(current) => {
println!("线程{}获取任务失败,当前状态: {:?}", i, current);
}
}
});
handles.push(handle);
}
// 主线程监控任务状态
let mut previous_status = status.load(Ordering::Acquire);
println!("监控开始,当前状态: {:?}", previous_status);
while status.load(Ordering::Acquire) == TaskStatus::Pending {
thread::sleep(Duration::from_millis(10));
}
let final_status = status.load(Ordering::Acquire);
println!("任务最终状态: {:?}", final_status);
// 等待所有线程完成
for handle in handles {
handle.join().unwrap();
}
// 演示状态转换
println!("\n状态转换演示:");
let demo_status = AtomicTaskStatus::new(TaskStatus::Pending);
// 状态转换序列
let transitions = [
(TaskStatus::Pending, TaskStatus::Processing, "开始处理"),
(TaskStatus::Processing, TaskStatus::Success, "处理成功"),
(TaskStatus::Success, TaskStatus::Pending, "重置任务"),
];
for (from, to, description) in transitions.iter() {
match demo_status.compare_exchange(
*from,
*to,
Ordering::SeqCst,
Ordering::Relaxed
) {
Ok(_) => {
println!("{}: {:?} -> {:?}", description, from, to);
}
Err(actual) => {
println!("状态转换失败,期望: {:?}, 实际: {:?}", from, actual);
}
}
thread::sleep(Duration::from_millis(100));
}
}
注意事项
- 枚举的变体数量不能超过255个
- 枚举的底层表示必须能够用单个字节表示
- 建议使用默认的
Ordering::SeqCst
以确保最强的内存排序保证 - 在性能关键场景中,可以根据需要选择更宽松的内存排序
atomic_enum库为Rust开发者提供了简单而高效的线程安全枚举操作方案,特别适合状态机和并发控制场景。