天天看點

設計模式複習-單例模式

設計模式複習-單例模式
#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來解決問題,感興趣的可以了解一下,我的思路是用彙編處理這個地方。不管用什麼方式,注意一點,就是編譯器會對我們的代碼進行優化。也就是變換了很多姿勢,最後轉出來的彙編是一樣的。這個地方要注意。