How to Avoid Deadlocks with Global Maps in Rust Using RwLock and lazy_static

This article walks through implementing a global HashMap in Rust with lazy_static and RwLock, demonstrates common deadlock pitfalls when mixing read and write guards, and provides revised code that separates lifetimes to safely retrieve and remove entries without hanging.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
How to Avoid Deadlocks with Global Maps in Rust Using RwLock and lazy_static

Rust has attracted a lot of attention since 2018, and the formation of the Rust Foundation in 2021 brought major players such as Amazon, Google, Microsoft, and Huawei into the ecosystem. After experimenting with a CLI framework, the author decided to try building a server‑side framework with axum and encountered several challenges.

Using a Global Map with lazy_static and RwLock

In many Rust projects a global variable is used to store shared data. The common approach is to combine lazy_static (or once_cell) with RwLock to create a static collection.

use std::collections::HashMap;
use std::sync::RwLock;

lazy_static::lazy_static! {
    static ref GLOBAL_MAP: RwLock<HashMap<String, String>> =
        RwLock::new({
            let map = HashMap::new();
            map
        });
}

Basic insert and read functions are implemented as follows:

fn insert_global_map(k: String, v: String) {
    let mut gpw = GLOBAL_MAP.write().unwrap();
    gpw.insert(k, v);
}

fn print_global_map() {
    let gpr = GLOBAL_MAP.read().unwrap();
    for pair in gpr.iter() {
        println!("{:?}", pair);
    }
}

Running the program prints the three key‑value pairs that were inserted:

("0", "0")
("1", "1")
("2", "2")

Adding a Get‑and‑Remove Operation

The next step is to retrieve a value by key and delete it. An initial implementation looked like this:

fn get_and_remove(k: String) {
    println!("execute get_and_remove");
    let gpr = GLOBAL_MAP.read().unwrap();
    let v = gpr.get(&*k.clone());
    let mut gpw = GLOBAL_MAP.write().unwrap();
    gpw.remove(&*k.clone());
}

The program hangs after printing "execute get_and_remove". The deadlock occurs because the read guard gpr is held while a write guard gpw is acquired, violating Rust's borrowing rules for RwLock.

Fixing the Deadlock by Splitting Lifetimes

To resolve the issue, the read and write phases are separated into distinct scopes so that the read guard is dropped before the write guard is created.

fn get_and_remove(k: String) {
    // Read phase – obtain the value and drop the read guard
    let v = {
        let gpr = GLOBAL_MAP.read().unwrap();
        match gpr.get(&*k) {
            Some(val) => val.clone(),
            None => return,
        }
    };
    // Write phase – acquire a write guard and remove the entry
    let mut gpw = GLOBAL_MAP.write().unwrap();
    gpw.remove(&*k);
    println!("get value is {:?}", v);
}

Running the corrected program produces the expected output:

("1", "1")
("0", "0")
("2", "2")
get value is "1"
("0", "0")
("2", "2")
finished!

This example demonstrates how Rust's lifetime system helps prevent subtle concurrency bugs, and how careful separation of read‑only and mutable access can avoid deadlocks when using global state.

Rust global map illustration
Rust global map illustration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

concurrencydeadlockglobal-staterwlocklazy_static
JD Cloud Developers
Written by

JD Cloud Developers

JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.