#access-key #semaphore #key #thread #access-control #shared-key

semaphore-key

使用共享信号量通过键控制并发线程访问的 Rust 库

7 个版本 (稳定)

1.0.4 2023年2月12日
1.0.3 2023年1月22日
0.2.0 2022年12月30日
0.1.0 2022年12月29日

#326 in 并发

LGPL-2.1-only

17KB
60

semaphore-key

使用共享信号量通过键来控制并发线程的访问。

该库内部维护一个静态的信号量哈希表,通过键的字符串类型索引,方便地通过公共 API 进行管理,从而消除了在您自己的项目中维护此类映射和同步的开销。请参阅示例以获取实现细节。

Crates.io

在 Crates.io 上发布

https://crates.io/crates/semaphore-key

使用方法

在您的项目中

按照以下指示添加 semaphore-key 依赖项,并查看示例代码。更多可运行的示例可以在 GitHub 的 'examples' 目录中找到。

[dependencies]
semaphore-key = "1.0.4"
use log::{info};
use semaphore_key::SemaphoreKey;
use std::{thread, time::Duration};

#[tokio::main]
async fn main() {
    
    simple_logger::init_with_level(log::Level::Info).unwrap();

    //Spawn 3 tasks in parallel.
    //The method "do_work" only allows 1 thread access at a time for a specific key.
    //Tasks one and two are using the same key, "foo", and will execute one after another,
    //while task three is using key a different key, "bar", and will execute simultaneously with task one.

    let join_handle_one = tokio::spawn(async {
        do_work("foo").await;
    });

    let join_handle_two = tokio::spawn(async {
        do_work("foo").await;
    });

    let join_handle_three = tokio::spawn(async {
        do_work("bar").await;
    });

    let (one, two, three) = tokio::join!(join_handle_one, join_handle_two, join_handle_three);

    one.unwrap();
    two.unwrap();
    three.unwrap();

    //optional remove created semaphore from internal static store,
    //if not needed anymore, otherwise keep in for the next method call.
    SemaphoreKey::remove_if_exists(&"foo".to_string()).await;
    SemaphoreKey::remove_if_exists(&"bar".to_string()).await;
}

//do_work only allows 1 thread access at a time for a specific key
//which is indicated by the allowed_concurrent_threads variable
async fn do_work(key: &str) {

    let allowed_concurrent_threads = 1;

    info!("Thread:{:?} entering method", thread::current().id());

    //if a semaphore does not exists for the provided key,
    //one is created and stored in the internal semaphore key map.

    let semaphore = SemaphoreKey::get_or_create_semaphore(
                            &key.to_string(), 
                            allowed_concurrent_threads).await;

    //acquire the permit

    let _permit = semaphore.acquire().await.unwrap();

    info!(
        "Thread:{:?} going to rest for 5 seconds",
        thread::current().id()
    );

    //rest for 5 seconds
    thread::sleep(Duration::from_millis(5000));

    info!("Thread:{:?} done with resting", thread::current().id());

    //the acquired permit is dropped here 
    //when the method goes out of scope.
    //allowing other waiting threads to continue
}

依赖项

~2–3MB
~49K SLoC