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()
        }
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM