Struct core::sync::atomic::AtomicUsize
1.0.0 · source · #[repr(C, align(8))]pub struct AtomicUsize { /* private fields */ }
Expand description
可以在线程之间安全共享的整数类型。
此类型与基本整数类型 [` 具有相同的内存表示形式
usize `]. 有关原子类型和非原子类型之间的区别以及有关此类型的可移植性的更多信息,请参见 模块级文档。
Note: 此类型仅在支持原子负载和 [` 的存储的平台上可用
usize `].
Implementations§
source§impl AtomicUsize
impl AtomicUsize
const: unstable · sourcepub unsafe fn from_ptr<'a>(ptr: *mut usize) -> &'a AtomicUsize
🔬This is a nightly-only experimental API. (atomic_from_ptr
#108652)
pub unsafe fn from_ptr<'a>(ptr: *mut usize) -> &'a AtomicUsize
atomic_from_ptr
#108652)从指针创建一个新的引用到原子整数。
Examples
#![feature(atomic_from_ptr, pointer_is_aligned)]
use std::sync::atomic::{self, AtomicUsize};
use std::mem::align_of;
// 获取指向分配值的指针
let ptr: *mut usize = Box::into_raw(Box::new(0));
assert!(ptr.is_aligned_to(align_of::<AtomicUsize>()));
{
// 创建分配值的原子视图
let atomic = unsafe {AtomicUsize::from_ptr(ptr) };
// 使用 `atomic` 进行原子操作,可能与其他线程共享
atomic.store(1, atomic::Ordering::Relaxed);
}
// 可以非原子地访问 `ptr` 后面的值,因为对原子的引用在上面的块中结束了它的生命周期
assert_eq!(unsafe { *ptr }, 1);
// 释放值
unsafe { drop(Box::from_raw(ptr)) }
RunSafety
ptr
必须与align_of::<AtomicBool>()
对齐 (请注意,在某些平台上,它可能比align_of::<bool>()
大)。ptr
must be aligned toalign_of::<AtomicUsize>()
(note that on some platforms this can be bigger thanalign_of::<usize>()
).- 对于整个生命周
'a
的读取和写入,ptr
必须是 valid。 - 整个生命周
'a
都不能通过非原子操作访问到ptr
后面的值。
sourcepub fn from_mut(v: &mut usize) -> &mut Self
🔬This is a nightly-only experimental API. (atomic_from_mut
#76314)
pub fn from_mut(v: &mut usize) -> &mut Self
atomic_from_mut
#76314)Get atomic access to a &mut usize
.
Note: This function is only available on targets where usize
has an alignment of 8 bytes.
Examples
#![feature(atomic_from_mut)]
use std::sync::atomic::{AtomicUsize, Ordering};
let mut some_int = 123;
let a = AtomicUsize::from_mut(&mut some_int);
a.store(100, Ordering::Relaxed);
assert_eq!(some_int, 100);
Runsourcepub fn get_mut_slice(this: &mut [Self]) -> &mut [usize]
🔬This is a nightly-only experimental API. (atomic_from_mut
#76314)
pub fn get_mut_slice(this: &mut [Self]) -> &mut [usize]
atomic_from_mut
#76314)Get non-atomic access to a &mut [AtomicUsize]
slice
这是安全的,因为可变引用保证没有其他线程同时访问原子数据。
Examples
#![feature(atomic_from_mut, inline_const)]
use std::sync::atomic::{AtomicUsize, Ordering};
let mut some_ints = [const { AtomicUsize::new(0) }; 10];
let view: &mut [usize] = AtomicUsize::get_mut_slice(&mut some_ints);
assert_eq!(view, [0; 10]);
view
.iter_mut()
.enumerate()
.for_each(|(idx, int)| *int = idx as _);
std::thread::scope(|s| {
some_ints
.iter()
.enumerate()
.for_each(|(idx, int)| {
s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
})
});
Runsourcepub fn from_mut_slice(v: &mut [usize]) -> &mut [Self]
🔬This is a nightly-only experimental API. (atomic_from_mut
#76314)
pub fn from_mut_slice(v: &mut [usize]) -> &mut [Self]
atomic_from_mut
#76314)Get atomic access to a &mut [usize]
slice.
Examples
#![feature(atomic_from_mut)]
use std::sync::atomic::{AtomicUsize, Ordering};
let mut some_ints = [0; 10];
let a = &*AtomicUsize::from_mut_slice(&mut some_ints);
std::thread::scope(|s| {
for i in 0..a.len() {
s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
}
});
for (i, n) in some_ints.into_iter().enumerate() {
assert_eq!(i, n as usize);
}
Run1.15.0 (const: unstable) · sourcepub fn into_inner(self) -> usize
pub fn into_inner(self) -> usize
sourcepub fn store(&self, val: usize, order: Ordering)
pub fn store(&self, val: usize, order: Ordering)
将值存储到原子整数中。
store
需要一个 Ordering
参数,它描述了这个操作的内存顺序。
可能的值为 SeqCst
,Release
和 Relaxed
。
Panics
如果 order
是 Acquire
或 AcqRel
,就会出现 panics。
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let some_var = AtomicUsize::new(5);
some_var.store(10, Ordering::Relaxed);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
Runsourcepub fn swap(&self, val: usize, order: Ordering) -> usize
pub fn swap(&self, val: usize, order: Ordering) -> usize
将值存储到原子整数中,返回前一个值。
swap
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let some_var = AtomicUsize::new(5);
assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
Runsourcepub fn compare_and_swap(
&self,
current: usize,
new: usize,
order: Ordering
) -> usize
👎Deprecated since 1.50.0: Use compare_exchange
or compare_exchange_weak
instead
pub fn compare_and_swap( &self, current: usize, new: usize, order: Ordering ) -> usize
compare_exchange
or compare_exchange_weak
instead如果当前值与 current
值相同,则将值存储到原子整数中。
返回值始终是前一个值。如果等于 current
,则该值已更新。
compare_and_swap
还带有一个 Ordering
参数,它描述了此操作的内存顺序。
请注意,即使使用 AcqRel
,该操作也可能失败,因此仅执行 Acquire
加载,但没有 Release
语义。
如果发生此操作,则使用 Acquire
使其成为该操作 Relaxed
的存储部分,而使用 Release
使该操作成为存储部分 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
迁移到 compare_exchange
和 compare_exchange_weak
compare_and_swap
等效于 compare_exchange
,具有以下内存排序映射:
Original | Success | Failure |
---|---|---|
Relaxed | Relaxed | Relaxed Acquire |
即使比较成功,compare_exchange_weak
也允许虚假失败,这允许编译器在循环中使用比较和交换时生成更好的汇编代码。
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let some_var = AtomicUsize::new(5);
assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
Run1.10.0 · sourcepub fn compare_exchange(
&self,
current: usize,
new: usize,
success: Ordering,
failure: Ordering
) -> Result<usize, usize>
pub fn compare_exchange( &self, current: usize, new: usize, success: Ordering, failure: Ordering ) -> Result<usize, usize>
如果当前值与 current
值相同,则将值存储到原子整数中。
返回值是指示是否写入了新值并包含先前值的结果。
成功后,此值保证等于 current
。
compare_exchange
需要两个 Ordering
参数来描述这个操作的内存顺序。
success
描述了在与 current
的比较成功时发生的读取 - 修改 - 写入操作所需的顺序。
failure
描述了比较失败时发生的加载操作所需的排序。
使用 Acquire
作为成功排序,使存储成为操作 Relaxed
的一部分,而使用 Release
,则使装载成功 Relaxed
。
故障顺序只能是 SeqCst
、Acquire
或 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let some_var = AtomicUsize::new(5);
assert_eq!(some_var.compare_exchange(5, 10,
Ordering::Acquire,
Ordering::Relaxed),
Ok(5));
assert_eq!(some_var.load(Ordering::Relaxed), 10);
assert_eq!(some_var.compare_exchange(6, 12,
Ordering::SeqCst,
Ordering::Acquire),
Err(10));
assert_eq!(some_var.load(Ordering::Relaxed), 10);
Run1.10.0 · sourcepub fn compare_exchange_weak(
&self,
current: usize,
new: usize,
success: Ordering,
failure: Ordering
) -> Result<usize, usize>
pub fn compare_exchange_weak( &self, current: usize, new: usize, success: Ordering, failure: Ordering ) -> Result<usize, usize>
如果当前值与 current
值相同,则将值存储到原子整数中。
Unlike AtomicUsize::compare_exchange
,
即使比较成功,此函数也可能会虚假地失败,这可能导致某些平台上的代码效率更高。
返回值是指示是否写入了新值并包含先前值的结果。
compare_exchange_weak
需要两个 Ordering
参数来描述这个操作的内存顺序。
success
描述了在与 current
的比较成功时发生的读取 - 修改 - 写入操作所需的顺序。
failure
描述了比较失败时发生的加载操作所需的排序。
使用 Acquire
作为成功排序,使存储成为操作 Relaxed
的一部分,而使用 Release
,则使装载成功 Relaxed
。
故障顺序只能是 SeqCst
、Acquire
或 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let val = AtomicUsize::new(4);
let mut old = val.load(Ordering::Relaxed);
loop {
let new = old * 2;
match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
Ok(_) => break,
Err(x) => old = x,
}
}
Runsourcepub fn fetch_add(&self, val: usize, order: Ordering) -> usize
pub fn fetch_add(&self, val: usize, order: Ordering) -> usize
加到当前值,返回前一个值。
此操作在溢出时回绕。
fetch_add
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(0);
assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
assert_eq!(foo.load(Ordering::SeqCst), 10);
Runsourcepub fn fetch_sub(&self, val: usize, order: Ordering) -> usize
pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize
从当前值中减去,返回前一个值。
此操作在溢出时回绕。
fetch_sub
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(20);
assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
assert_eq!(foo.load(Ordering::SeqCst), 10);
Runsourcepub fn fetch_and(&self, val: usize, order: Ordering) -> usize
pub fn fetch_and(&self, val: usize, order: Ordering) -> usize
“and” 按位与当前值。
对当前值和参数 val
执行按位 “and” 运算,并将新值设置为结果。
返回前一个值。
fetch_and
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(0b101101);
assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
Run1.27.0 · sourcepub fn fetch_nand(&self, val: usize, order: Ordering) -> usize
pub fn fetch_nand(&self, val: usize, order: Ordering) -> usize
“nand” 按位与当前值。
对当前值和参数 val
执行按位 “nand” 运算,并将新值设置为结果。
返回前一个值。
fetch_nand
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(0x13);
assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
Runsourcepub fn fetch_or(&self, val: usize, order: Ordering) -> usize
pub fn fetch_or(&self, val: usize, order: Ordering) -> usize
“or” 按位与当前值。
对当前值和参数 val
执行按位 “or” 运算,并将新值设置为结果。
返回前一个值。
fetch_or
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(0b101101);
assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
Runsourcepub fn fetch_xor(&self, val: usize, order: Ordering) -> usize
pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize
“xor” 按位与当前值。
对当前值和参数 val
执行按位 “xor” 运算,并将新值设置为结果。
返回前一个值。
fetch_xor
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(0b101101);
assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
Run1.45.0 · sourcepub fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F
) -> Result<usize, usize>where
F: FnMut(usize) -> Option<usize>,
pub fn fetch_update<F>( &self, set_order: Ordering, fetch_order: Ordering, f: F ) -> Result<usize, usize>where F: FnMut(usize) -> Option<usize>,
获取该值,并对其应用一个函数,该函数返回一个可选的新值。如果函数返回 Some(_)
,则返回 Ok(previous_value)
的 Result
,否则返回 Err(previous_value)
。
Note: 如果与此同时从其他线程更改了值,则只要函数返回 Some(_)
,这可能会多次调用该函数,但是该函数仅对存储的值应用一次。
fetch_update
需要两个 Ordering
参数来描述这个操作的内存顺序。
第一个描述了操作最终成功时所需的顺序,第二个描述了负载所需的顺序。这些对应于成功和失败的顺序
AtomicUsize::compare_exchange
respectively.
使用 Acquire
作为成功排序,使存储成为该操作 Relaxed
的一部分,而使用 Release
,则使最终成功加载 Relaxed
。
(failed) 加载顺序只能是 SeqCst
、Acquire
或 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Considerations
这种方法并不神奇; 它不是由硬件提供的。
它是按照以下方式实现的
AtomicUsize::compare_exchange_weak
,
并遭受同样的缺点。
特别是,这种方法不会绕过 ABA Problem。
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let x = AtomicUsize::new(7);
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
assert_eq!(x.load(Ordering::SeqCst), 9);
Run1.45.0 · sourcepub fn fetch_max(&self, val: usize, order: Ordering) -> usize
pub fn fetch_max(&self, val: usize, order: Ordering) -> usize
当前值的最大值。
查找当前值和参数 val
的最大值,并将新值设置为结果。
返回前一个值。
fetch_max
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(23);
assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
assert_eq!(foo.load(Ordering::SeqCst), 42);
Run如果要一步获得最大值,可以使用以下方法:
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(23);
let bar = 42;
let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
assert!(max_foo == 42);
Run1.45.0 · sourcepub fn fetch_min(&self, val: usize, order: Ordering) -> usize
pub fn fetch_min(&self, val: usize, order: Ordering) -> usize
当前值的最小值。
查找当前值和参数 val
的最小值,并将新值设置为结果。
返回前一个值。
fetch_min
需要一个 Ordering
参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。
请注意,使用 Acquire
会使该操作成为存储部分 Relaxed
,而使用 Release
会使装入部分成为 Relaxed
。
Note: 此方法仅在支持原子操作的平台上可用
Examples
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(23);
assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
assert_eq!(foo.load(Ordering::Relaxed), 23);
assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
assert_eq!(foo.load(Ordering::Relaxed), 22);
Run如果要一步获得最小值,则可以使用以下方法:
use std::sync::atomic::{AtomicUsize, Ordering};
let foo = AtomicUsize::new(23);
let bar = 12;
let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
assert_eq!(min_foo, 12);
Run1.70.0 (const: 1.70.0) · sourcepub const fn as_ptr(&self) -> *mut usize
pub const fn as_ptr(&self) -> *mut usize
返回指向底层整数的可变指针。
在结果整数上进行非原子读取和写入可以是数据竞争。
此方法对于 FFI 最为有用,在 FFI 中可能使用函数签名
*mut usize
instead of &AtomicUsize
.
从共享引用返回 *mut
指针到此原子是安全的,因为原子类型可与内部可变性一起使用。
原子的所有修改都通过共享的 quot 更改值,并且只要它们使用原子操作就可以安全地进行更改。
对返回的裸指针的任何使用都需要一个 unsafe
块,并且仍然必须遵守相同的限制:对其进行的操作必须是原子的。