7个版本

0.4.0 2023年1月5日
0.3.3 2023年10月30日
0.3.2 2023年9月11日
0.3.1 2022年8月27日
0.1.0 2021年3月4日

#166 in 嵌入式开发

每月37次下载
2个crate中使用(通过memac

自定义许可证

24KB
495

Rust中no_std环境的同步工具

MCS锁

MCS锁是一种公平且可扩展的互斥锁。它可以作为std::sync::Mutex使用。

use synctools::mcs;
use std::sync::Arc;
use std::vec::Vec;

const NUM_LOOP: usize = 10000000;
const NUM_THREADS: usize = 4;

fn main() {
    // create a MCSLock object
    let n = Arc::new(mcs::MCSLock::new(0));
    let mut v = Vec::new();

    for _ in 0..NUM_THREADS {
        let n0 = n.clone();
        let t = std::thread::spawn(move || {
            let mut node = mcs::MCSNode::new();
            for _ in 0..NUM_LOOP {
                // lock and acquire the reference
                let mut r = n0.lock(&mut node);

                // increment atomically
                *r += 1;
            }
        });

        v.push(t);
    }

    for t in v {
        t.join().unwrap();
    }

    let mut node = mcs::MCSNode::new();
    let r = n.lock(&mut node);
    assert_eq!(NUM_LOOP * NUM_THREADS, *r);
}

读写锁

基于自旋锁的读写锁可以用来作为std::sync::RwLock。

use synctools::rwlock;
use std::sync::Arc;
use std::vec::Vec;

const NUM_LOOP: usize = 10000000;
const NUM_THREADS: usize = 4;

fn main() {
    // create a RwLock object
    let n = Arc::new(rwlock::RwLock::new(0));
    let mut v = Vec::new();

    // reader
    for _ in 0..(NUM_THREADS - 1) {
        let n0 = n.clone();
        let t = std::thread::spawn(move || {
            for _ in 0..NUM_LOOP {
                // read lock
                let r = n0.read();
                assert_eq!(*r, 0);
            }
        });

        v.push(t);
    }

    // writer
    let n0 = n.clone();
    let wr = std::thread::spawn(move || {
        for _ in 0..NUM_LOOP {
            {
                // write lock
                let mut r = n0.write();
                *r += 1;
                *r -= 1;
            }
        }
    });

    v.push(wr);

    for t in v {
        t.join().unwrap();
    }
}

无锁栈(仅限AArch64)

无锁栈是一个并发数据结构。这只能在AArch64和nightly版本中使用,因为它在内部使用了内联汇编中的LL/SC指令。

use synctools::lfstack;
use std::sync::Arc;
use std::vec::Vec;

const NUM_LOOP: usize = 10000000;
const NUM_THREADS: usize = 4;

fn main() {
    // create a stack
    let mut stack = Arc::new(lfstack::LFStack::<usize>::new());
    let mut v = Vec::new();

    for i in 0..NUM_THREADS {
        let mut stack0 = stack.clone();
        let t = std::thread::spawn(move || {
            if i & 1 == 0 { // even thread
                for j in 0..NUM_LOOP {
                    let k = i * NUM_LOOP + j;
                    // push k to the stack
                    stack0.get_mut().push(k);
                }
            } else { // odd thread
                for _ in 0..NUM_LOOP {
                    loop {
                        // pop from the stack
                        if let Some(k) = stack0.get_mut().pop() {
                            break;
                        }
                    }
                }
            }
        });
        v.push(t);
    }

    for t in v {
        t.join().unwrap();
    }

    assert_eq!(stack.get_mut().pop(), None);
}

如何测试

运行

$ cargo +nightly test

对于AArch64,或者

$ cargo +nightly test --no-default-features

对于非AArch64环境。

依赖项

~0–24MB
~334K SLoC