具有原子读写功能的 Mutex<bool>

at5*_*321 4 concurrency mutex rust

我需要有一个可由多个线程访问的全局布尔标志。

这是我需要的示例:

static GLOBAL_FLAG: SyncLazy<Mutex<bool>> = SyncLazy::new(|| {
    Mutex::new(false)
});

fn set_flag_to_true() {  // can be called by 2+ threads concurrently 
    *GLOBAL_FLAG.lock().unwrap() = true;
}

fn get_flag_and_set_to_true() -> bool {  // only one thread is calling this function
    let v = *GLOBAL_FLAG.lock().unwrap();  // Obtain current flag value
    *GLOBAL_FLAG.lock().unwrap() = true;  // Always set the flag to true
    v  // Return the previous value
}
Run Code Online (Sandbox Code Playgroud)

实施get_flag_and_set_to_true()感觉不太正确。我想最好只锁一次。最好的方法是什么?

顺便说一句,我想Arc<[AtomicBool]>也可以使用,并且理论上应该更快,尽管在我的特殊情况下,速度优势将不明显。

use*_*342 7

顺便说一句,我想Arc<[AtomicBool]>也可以使用,并且理论上应该更快,尽管在我的特殊情况下,速度优势将不明显。

这不仅涉及性能方面的优势,还涉及代码量和代码推理的便利性。AtomicBool您不需要互斥SyncLazy锁,并且代码更短更清晰:

use std::sync::atomic::{AtomicBool, Ordering};

static GLOBAL_FLAG: AtomicBool = AtomicBool::new(false);

pub fn set_flag_to_true() {
    GLOBAL_FLAG.store(true, Ordering::SeqCst);
}

pub fn get_flag_and_set_to_true() -> bool {
    GLOBAL_FLAG.swap(true, Ordering::SeqCst)
}
Run Code Online (Sandbox Code Playgroud)

操场

  • @Stargateur当您需要使用它来同步其他不安全的数据结构时,这很复杂。在这种情况下,与“Mutex”相比,它确实很简单。 (3认同)

lko*_*bly 6

GLOBAL_FLAG可以想象,当您阅读和设置为 true 时,可能会出现另一个线程GLOBAL_FLAG。要解决此问题,您可以直接存储返回的MutexGuarddocsGLOBAL_FLAG.lock().unwrap()

fn get_flag_and_set_to_true() -> bool {  // only one thread is calling this function
    let mut global_flag = GLOBAL_FLAG.lock().unwrap();
    let v = *global_flag;  // Obtain current flag value
    *global_flag = true;  // Always set the flag to true
    v  // Return the previous value
}
Run Code Online (Sandbox Code Playgroud)

global_flag将保持互斥体锁定,直到它被删除。