#pragma once
#include "stdafx.h"
#include<set>
#include<string>
#include<iostream>
using namespace std;
/*
設計模式-單例模式(Singleton)
保證一個類僅有一個執行個體,并提供一個通路它的全局通路節點。
[懶漢模式涉及多線程上鎖問題,餓漢模式不涉及多線程上鎖問題]
下面實作懶漢跟餓漢模式,先不考慮上鎖問題,最後補充。
*/
/*
設計模式-疊代器模式(Iterator)
提供一種方法順序通路一個聚合對象中的各個元素,而不暴露該對象内部表示。
(現在好多語言都已經内置實作了這個功能了,是以實際用途不大,
但是建議寫一下,實作過程價值遠遠大于使用價值。)
*/
//懶漢模式
class Cwork {
private:
static Cwork *m_cWork;
static int m_nMarkRunCount;
Cwork() {}//注意,構造函數私有化可以限制其他人去執行個體化這個類。
void DoWrite() {
cout << "WorkCiunt:" << m_nMarkRunCount++ << endl;
}
public:
static void GetInstance() {
if (m_cWork == NULL) {
m_cWork = new Cwork();
}
}
static void WrkteLog() {
if (m_cWork == NULL) {
cout << "no instance" << endl;
return;
}
m_cWork->DoWrite();
}
};
Cwork * Cwork::m_cWork = NULL;
int Cwork::m_nMarkRunCount = 0;
int main() {
Cwork::WrkteLog();
Cwork::GetInstance();
Cwork::WrkteLog();
getchar();
return 0;
}
#pragma once
#include "stdafx.h"
#include<set>
#include<string>
#include<iostream>
using namespace std;
//餓漢模式
class Cwork {
private:
static Cwork *m_cWork;
static int m_nMarkRunCount;
Cwork() {}//注意,構造函數私有化可以限制其他人去執行個體化這個類。
void DoWrite() {
cout << "WorkCiunt:" << m_nMarkRunCount++ << endl;
}
public:
static Cwork* GetInstance() {
if (m_cWork == NULL) {
m_cWork = new Cwork();
}
return m_cWork;
}
static void WrkteLog() {
if (m_cWork == NULL) {
cout << "no instance" << endl;
return;
}
m_cWork->DoWrite();
}
};
Cwork * Cwork::m_cWork = Cwork::GetInstance();
int Cwork::m_nMarkRunCount = 0;
int main() {
Cwork::WrkteLog();
Cwork::WrkteLog();
getchar();
return 0;
}
還有就是鎖的問題。多線程環境下使用單例模式中的懶漢模式會涉及到上鎖問題,主要是在這個地方:
上面是一個傳統的上鎖模式,但是這個會有一個資源浪費問題,就是雖然m_cWork已經不等于NULL了,但是還是會不停的上鎖和解鎖,上鎖和解鎖涉及到核心态和使用者态的轉換,這回導緻資源浪費。于是便引出了雙重鎖的概念,雙重鎖全稱雙重檢查鎖定模式,縮寫DCLP。
大體姿勢是這樣:
Static void GetInstance(){
If(m_cWork == NULL){
Lock{
If(m_cWork == NULL){
m_cWork = new CWork();
}
}
}
}
但是繼續延伸一下,根據這裡的分析:雙重鎖也是不餓穩定的,那篇文章裡引入了volatile來解決問題,感興趣的可以了解一下,我的思路是用彙編處理這個地方。不管用什麼方式,注意一點,就是編譯器會對我們的代碼進行優化。也就是變換了很多姿勢,最後轉出來的彙編是一樣的。這個地方要注意。