#智能指针 #并行 #数据结构

spinout

类似于 Arc<Mutex<T>> 的线程安全、可克隆和可变的智能指针,使用自旋锁而不是系统 futex

3 个版本

0.0.12 2022 年 9 月 28 日
0.0.11 2022 年 9 月 28 日
0.0.1 2022 年 9 月 28 日

#683并发

MIT/Apache

20KB
352

Atom

这是一个实验性实现,这意味着 API 可能会更改,也可能出现错误。

同步和可变智能指针类型 Atom<T> 及其 Weak<T> 变体的实验性 API。还包括相关的自旋锁类型 SpinLock

Mutex<T> 不同,Atom<T> 不使用系统 futex,而是使用简单的自旋锁。在低竞争情况下(即锁仅保持短暂时间且竞争锁的线程很少)可能会有所优势。

用法

Atom<T> 模仿 Arc<Mutex<T>> 的行为,但 API 略有不同。我们不是使用锁卫,而是在闭包中直接访问内部 T

let atom = Atom::new(5);
atom.lock(|x| *x += 5);
assert_eq!(atom.get(), 10);

我们可以访问内部值的部分并将其映射到新的值

let atom = Atom::new(vec![1, 2, 3]);
let sum: i32 = atom.map(|x| x.iter().sum());
assert_eq!(sum, 6);

或者修改并映射

let atom = Atom::new(vec![1, 2, 3]);
let three = atom.map_mut(|x| x.pop());
assert_eq!(three, Some(3));
assert_eq!(atom.get(), vec![1, 2]);

示例

use spinout::Atom;

fn main() {

    let mut numbers = vec![];

    for i in 1..43 {
        numbers.push(i);
    }

    let numbers = Atom::new(numbers);
    let t1_numbers = numbers.clone();
    let t2_numbers = numbers.clone();

    let results = Atom::new(vec![]);
    let t1_results = results.clone();
    let t2_results = results.clone();

    let t1 = std::thread::spawn(move || {
        while let Some(x) = t1_numbers.map_mut(|x| x.pop()) {
            if x % 2 == 0 {
                t1_results.lock(|v| v.push(x));
            }
        }
    });

    let t2 = std::thread::spawn(move || {
        while let Some(x) = t2_numbers.map_mut(|x| x.pop()) {
            if x % 2 == 0 {
                t2_results.lock(|v| v.push(x));
            }
        }
    });

    t1.join().unwrap();
    t2.join().unwrap();

    let mut results = results.get();

    results.sort();

    let expected = [
        2, 4, 6, 8, 10, 12, 14, 16,
        18, 20, 22, 24, 26, 28, 30,
        32, 34, 36, 38, 40, 42
    ];

    assert_eq!(results, expected);
}

基准测试

我们在 AMD Ryzen 3 3100 4 核处理器上使用 Criterion 统计基准测试工具运行了这些测试。

有四个不同的测试,模拟了一个具有少量线程和低竞争的现实世界场景。

Balanced Read and WriteRead Heavy Read and Write 中,我们对一个小的向量进行排序,并从(反转的)向量中读取最大值。

Balanced Read and Write Read Heavy Read and Write

Write Only 测试中,我们对一个小向量进行排序和反转。

Write Only

Read Only 测试中,我们在向量中查找一个值。

Read Only

无运行时依赖项