OnceLock, Arc and Mutex for global variable questions

Hi, I'm using OnceLock, Arc and Mutex to create a global singleton with thread safety, and it works fine already:

// An example
fn get_instance() -> &'static Arc<Mutex<String>> {
  static INSTANCE: OnceLock<Arc<Mutex<String>>> = OnceLock::new();
  INSTANCE.get_or_init(|| {
    Arc::new(Mutex::new(String::new()))
  })
}

// In some other thread
let lock = get_instance().lock().unwrap();

As the rust document says, Arc is an atomic reference counter for sharing ownerships, but in the example above it is already static, the lifetime is the whole program. I think here tracing the reference counter is unnecessary.

Can I replace OnceLock<Arc<Mutex<String>>> to OnceLock<Mutex<String>> so just make the get_instance function returns a &'static Mutex<String>?

If it is going to be around for the whole program anyway then you aren't really gaining anything from having Arc in there so you can just have a OnceLock<Mutex<String>> and pass references around. If you do that then you also don't need the OnceLock (both Mutex::new() and String::new() are const), so you can just have Mutex<String>.

5 Likes

If I need to initialize some non-const structures in Mutex, should I still need to use the OnceLock?

The OnceLock might still be useful, though, if you need one-time initialization that can’t be done with const— Especially if the empty string is a valid value and not just a sentinel for being uninitialized.

1 Like