c++:設計モードの単例モード(怠け者モード、餓漢モード)(一)


1、単例モードとは何ですか.
≪単一モード|Single Mode|emdw≫:クラスにはオブジェクトが1つしか作成できません.このモードでは、システム内のクラスにインスタンスが1つしかないことを保証し、すべてのプログラム・モジュールで共有されるグローバル・アクセス・ポイントを提供します.
一例モデルを実現する考え方:
1.シールド構造関数2.インタフェースを提供して一意のオブジェクトを生成
≪適用シーン|Apply Scene|emdw≫:たとえば、サーバー・プログラムでは、サーバーの構成情報がファイルに格納され、これらの構成データは1つのインスタンス・オブジェクトによって統一的に読み込まれ、サービス・プロセス内の他のオブジェクトがこのインスタンス・オブジェクトを介してこれらの構成情報を取得します.この方法により、複雑な環境での構成管理が簡素化されます.その他にも、システムのログ出力、MODEMの接続には1本の電話線が必要で、オペレーティングシステムにはウィンドウマネージャが1つしかなく、PCが1つのキーボードが1つしかありません.
単一のオブジェクトの作成時間によって、次の2つのモードに分けられます.
怠け者モード遅延ロード
餓漢モード貪欲ロード
一、怠け者モード
特徴:遅延ロード、時間交換空間.インスタンスオブジェクトを初めて使用する場合は、オブジェクトを作成します.プロセスは無負荷で開始されます.複数の単一インスタンスは、シーケンス自由制御を開始します.
怠け者モード:やむを得ずクラスをインスタンス化しません.つまり、クラスインスタンスを初めて使用したときにインスタンス化します.
≪適用シーン|Apply Scene|emdw≫:コンフィギュレーション・ファイル、プラグインのロード、ネットワーク接続の初期化、ファイルの読み取りなど、単一のオブジェクトの構築に時間がかかる場合や、多くのリソースが消費される場合、オブジェクト・プログラムの実行時に使用されない可能性があります.プログラムが最初から初期化されると、プログラムの起動が非常に遅くなります.だからこの場合は怠け者モードを使ったほうがいいです.
1.スレッドが安全でない単一のパターン
class Singleton
{
private:
    Singleton(){}
public:
    static Singleton* Instance();
private:
    static Singleton* ptr; 
};
Singleton* Singleton::ptr = NULL; 
Singleton* Singleton::Instance() 
{
    if (ptr == NULL)
    {
        ptr = new Singleton;
    }
    return ptr;
}


このメソッドはスレッドが安全ではありません.2つのスレッドがgetInstanceメソッドを同時に最初に呼び出すことを考慮すると、1つのオブジェクトだけが生成されません.2つのスレッドが同時にInstanceメソッドを呼び出し、ptrがNULL値であることを同時に検出することを考慮すると、2つのスレッドは同時にptrにインスタンスを構築します.
2.ダブルロックスレッドセキュリティ版
class SingleTon
{
public:
	static SingleTon* getInstance()
	{
		if (psingle == NULL)
		{
			lock();
			if (psingle == NULL)
			{
				psingle = new SingleTon();
			}
			unlock();
		}
		return psingle;
	}
private:
	SingleTon(){}
	SingleTon(const SingleTon&);
	static SingleTon* psingle;
};
SingleTon* SingleTon::psingle = NULL;
int main()
{
	return 0;
}

考え方の解釈:
  • まず関数プライベートを構築し、他人が勝手にオブジェクトを作成しないようにすると同時にコピー防止の作業を行うために、コピーコンストラクタと付与演算子をプライベートに再ロードし、C++98はこの2つの関数を実現しないと宣言するだけで、C++11でdeleteを使用してこの2つの関数を削除することができます.
  • は、コンパイル中にリソースを消費することができないため、コンパイル時にポインタを1つだけ作成し、ポインタを作成する消費は
  • ではありません.
  • は、インタフェースを提供し、インタフェースの内部でnewを使用してオブジェクトを作成するので、psingle=new SingleTon()である.
  • ですが、そうするとこの共通のインタフェースを呼び出すたびにオブジェクトが生成されるので、このとき判断条件を付けて、ポインタが空であればオブジェクトを作成し、ポインタが空でなければそのオブジェクトのポインタを返します.
  • は、上記のように基本的に単一の例を完了したが、インタフェースを呼び出すために複数のスレッドがある場合、複数のスレッドが同時にアクセスし、複数のオブジェクトが作成されるという深刻な問題がある.スレッドの安全のためにはロックが必要であり、ロックをかけると並列のスレッドをシリアルにして実行することができ、この共通のインタフェースが毎回1つのスレッドでしかスケジューリングできないことを保証することができ、その後のスレッドは前のスレッドがロックを解放するまで待機されます.
  • にはもう一つの小さな効率の問題があります.スレッドが多いと、スレッドごとにロック解除ロックを申請すると効率に非常に影響します.そこで、ここでは二重検査を行い、外層に判断文を追加し、後回しのスレッドがこのポインタが空であることを発見したら直接戻ってくることを保証し、ロック解除操作を行う必要はありません.これにより、プログラム全体の効率が向上します.

  • 二、餓漢モード
    特徴:スペースチェンジ
    餓漢モード:単例類定義の際にインスタンス化する.main関数が実行される前に、グローバル役割ドメインのクラスメンバーの静的変数m_Instanceは初期化されているので、マルチスレッドの問題はありません.
    欠点:オブジェクトの作成初期化はコンパイル中に完了するため、プロセスの開始が遅くなり、複数の単一クラスオブジェクトインスタンスの起動順序が不確定な場合があります.
    class SingleTon
    {
    public:
    	static SingleTon* getInstance()
    	{
    		return psingle;
    	}
    private:
    	SingleTon(){}
    	SingleTon(const SingleTon&);
    	static SingleTon* psingle;
    };
    SingleTon* SingleTon::psingle = new SingleTon();
    

    特徴と選択:アクセス量が小さい場合、怠け者を採用して実現し、これは時間で空間を変える.アクセス量が比較的大きく、空腹漢を採用して実現され、これは空間で時間を変える.
    このブロガーは2つの怠け者モデルの実現方法を提供しており、参考にすることができます.
    C++で単例モード1-怠け者モードと餓漢式を実現