You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.8 KiB

全局变量

在一些场景我们可能需要全局变量来简化状态共享的代码包括全局ID全局数据存储等等下面我们来一一给出对应的实现方法。

全局唯一ID

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

struct Factory{
    factory_id: usize,
}

static GLOBAL_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
// This gives large room for ids to overflow
// This code assumes that your app never would need many factories
const MAX_ID: usize = usize::MAX / 2;

fn generate_id()->usize{
    // Check overflow twice to avoid growing of GLOBAL_ID_COUNTER after overflow.
    let current_val = GLOBAL_ID_COUNTER.load(Ordering::Relaxed);
    if current_val > MAX_ID{
        panic!("Factory ids overflowed");
    }
    let next_id = GLOBAL_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
    if next_id > MAX_ID{
        panic!("Factory ids overflowed");
    }
    next_id
}

impl Factory{
    fn new()->Self{
        Self{
            factory_id: generate_id()
        }
    }
}

从函数中返回全局变量

https://www.reddit.com/r/learnrust/comments/rqn74g/cant_a_function_return_a_reference_to_some_global/

lazy_static

use std::{sync::{Mutex, MutexGuard}, thread};
use std::thread::sleep;
use std::time::Duration;

use lazy_static::lazy_static;
lazy_static! {
    static ref MUTEX1: Mutex<i64> = Mutex::new(0);
    static ref MUTEX2: Mutex<i64> = Mutex::new(0);
}

fn main() {
    // Spawn thread and store handles
    let mut children = vec![];
    for i_thread in 0..2 {
        children.push(thread::spawn(move || {
            for _ in 0..1 {
                // Thread 1
                if i_thread % 2 == 0 {
                    // Lock mutex1
                    // No need to specify type but yes create a dummy variable to prevent rust
                    // compiler from being lazy
                    let _guard: MutexGuard<i64> = MUTEX1.lock().unwrap();

                    // Just log
                    println!("Thread {} locked mutex1 and will try to lock the mutex2, after a nap !", i_thread);

                    // Here I sleep to let Thread 2 lock mutex2
                    sleep(Duration::from_millis(10));

                    // Lock mutex 2
                    let _guard = MUTEX2.lock().unwrap();
                // Thread 2
                } else {
                    // Lock mutex 1
                    let _guard = MUTEX2.lock().unwrap();

                    println!("Thread {} locked mutex2 and will try to lock the mutex1", i_thread);

                    // Here I freeze !
                    let _guard = MUTEX1.lock().unwrap();
                }
            }
        }));
    }

    // Wait
    for child in children {
        let _ = child.join();
    }

    println!("This is not printed");
}

box::leak