Rust实现单例模式

先用一小段代码辅助说明结论(涉及多线程、多个可变引用下的实现)

use std::sync::Arc;
use std::sync::Mutex;

struct Point {
    pub x: u32,
    pub y: u32
}

impl Point {
    pub fn get_instance() -> Arc<Mutex<Point>> {
        static mut POINT: Option<Arc<Mutex<Point>>> = None;

        unsafe {// Rust中使用可变静态变量都是unsafe的
            POINT.get_or_insert_with(|| {
                // 初始化单例对象的代码
                Arc::new(Mutex::new(Point {x: 0, y: 0}))
            }).clone()
        }
    }
}
  • Option<...>作为静态变量来存储单例对象的原始全局指针,用get_or_insert_with方法来初始化单例对象
  • 最严谨的方法是用 Arc<Mutex<T>> 或者Arc<RwLock<T>>来持有单例对象;如果不需要单例对象的可变引用,直接用Arc<T>即可;如果是单线程程序,Arc可以可用Rc替代

为什么不用Box而是Arc/Rc?

Box表示唯一的指针引用,不能clone。单例对象是要被多处代码所引用的,Box<T>只能move不能clone,所以根本无法实现将一个Box<T>作为共享指针。

不需要可变引用的情况

如果不需要可变引用,那就没有必要使用Mutex或者RwLock了。可以返回一个Arc<T>或者&'static T

    pub fn get_instance() -> Arc<Point> {
        static mut POINT: Option<Arc<Point>> = None;

        unsafe {// Rust中使用可变静态变量都是unsafe的
            POINT.get_or_insert_with(|| {
                // 初始化单例对象的代码
                Arc::new(Point {x: 0, y: 0})
            }).clone()
        }
    }

    // 返回&'static Point
    pub fn get_instance() -> &'staic Point {
        static mut POINT: Option<Arc<Point>> = None;

        unsafe {// Rust中使用可变静态变量都是unsafe的
            POINT.get_or_insert_with(|| {
                // 初始化单例对象的代码
                Arc::new(Point {x: 0, y: 0})
            });
            POINT.as_ref().unwrap()
        }
    }

猜你喜欢

转载自www.cnblogs.com/metaworm/p/11969270.html