單例模式是最簡單的一種設計模式,保證⼀個類僅有⼀個例項,並提供⼀個該例項的全域性訪問點。
class
singleton
private
:singleton()
//構造
singleton
(const singleton&
)//拷貝構造
singleton &
operator=(
const singleton&
)static singleton *instance;
}singleton *singleton::instance =
null
;
這種的單例會有什麼問題呢?會有兩個問題,第乙個是有執行緒安全問題,第二個new的物件沒有delete,導致記憶體洩漏。那我們要怎麼改呢?加鎖!
class
singleton
return instance;
}private
:static
void
destructor()
singleton()
//構造
singleton
(const singleton&
)//拷貝構造
singleton &
operator=(
const singleton&
)static singleton *instance;
}singleton *singleton::instance =
null
;
新增了乙個析構函式atexit(),函式引數是乙個函式指標,函式指標指向乙個沒有引數也沒有返回值的函式。
#include
*intatexit(void(func)(void));
atexit()成功時返回零,失敗時返回非零。
這樣在函式退出時,就可以自動呼叫析構函式。
但是還是執行緒不安全。
3.
class
singleton
}return instance;
}private
:static
void
destructor()
singleton()
//構造
singleton
(const singleton&
)//拷貝構造
singleton &
operator=(
const singleton&
)static singleton *instance;
static std::mutex mutex;
}singleton *singleton::instance =
null
;std::mutex singleton::mutex;
//互斥鎖初始化
這裡需要double-check 來預防多執行緒帶來的問題。但是使用3.1的這樣的加鎖,不管instance 是不是null, 都會導致產生system call的問題,資源大大浪費,所以衍生出3.2這樣的加鎖方式。但是這樣也會帶來乙個問題,因為c++記憶體的reorder問題(推薦 這篇blog c++11的記憶體序)。
因為我們知道乙個class new乙個新物件的時候,會生成 1.分配記憶體;2.呼叫構造器;3.賦值操作。reorder操作就是不按這樣的順序進行初始化,如果有個執行緒先進行賦值操作,然後再呼叫構造器操作。會導致第二個執行緒查詢instance時,不為空,導致直接return。
class
singleton
}return tmp;
}private
:static
void
destructor()
singleton()
//構造
singleton
(const singleton&
)//拷貝構造
singleton &
operator=(
const singleton&
)static std::atomic> instance;
static std::mutex mutex;
}std::atomic> singleton::instance;
std::mutex singleton::mutex;
//互斥鎖初始化
對_instance進行原子操作,這樣就保證了執行緒安全。但是這樣是不是未免太麻煩了。c++ effective中提供了一種簡單的方案:
class
singleton
private
:singleton()
//構造
singleton
(const singleton&
)//拷貝構造
singleton &
operator=(
const singleton&
)static singleton *instance;
}singleton *singleton::instance =
null
;
這是c++11的 magic static 特性:如果當變數在初始化的時候,併發同時進⼊宣告語句,併發
執行緒將會阻塞等待初始化結束。
談談單例模式(一)
單例模式是一種很簡單,很常見的模式。我們創造並使用單例,一般是基於兩點考慮。1.全域性唯一。2.便利的訪問 更多的人的會考慮這個 那麼如何寫出乙個單例模式,寫乙個單例模式我們要思考那些東西,避免那些問題。下面是乙個c 實現的單利模式,不過只考慮了保證全域性只有乙個物件的問題。class single...
單例模式 單例模式
餓漢式 急切例項化 public class eagersingleton 2.宣告靜態成員變數並賦初始值 類初始化的時候靜態變數就被載入,因此叫做餓漢式 public static eagersingleton eagersingleton new eagersingleton 3.對外暴露公共的...
單例 單例模式
簡單的實現乙個單例 instancetype sharedinstance return instance 真正的單例模式 myclass sharedinstance return instance id allocwithzone nszone zone return nil id copywi...