C++Singleton単例モードを多様な方法で実現
テーマ:クラスを設計し、そのクラスのインスタンスを生成するしかありません.
(1)解法一:単一スレッド環境にのみ適用
インスタンスを1つしか生成できないことが要求されるため、コンストラクション関数をプライベート関数に設定して、インスタンスの作成を禁止する必要があります.静的インスタンスを定義し、必要に応じてインスタンスを作成できます.
上記のコードはSingleton 1の静的メソッドfuncInstance()では、instanceがnullの場合にのみインスタンスを作成して重複作成を回避し、コンストラクション関数をプライベート関数として定義することで、インスタンスが1つしか作成されないことを保証します.
(2)解法2:マルチスレッド環境では機能するが効率が悪い
解法1のコードは,単一スレッドの場合は正常に動作するが,マルチスレッドの場合は問題がある.2つのスレッドがinstanceがnullであるかどうかを判断するif文まで同時に実行され、instanceが実際に作成されていないと仮定すると、2つのスレッドはインスタンスを作成し、単一のモードの要件を満たさなくなります.
マルチスレッド環境でタイプのインスタンスしか得られないことを保証するには、同期ロックを追加する必要があります.次のようになります.
2つのスレッドが同時にインスタンスを作成したいと仮定します.同期ロックは、1つの時点で1つのスレッドしか得られないため、1つ目のスレッドがロックされると、2つ目のスレッドは待つしかありません.最初のスレッドがインスタンスがまだ作成されていないことを発見したとき、彼はインスタンスを作成しました.次に、最初のスレッドが同期ロックを解放し、2番目のスレッドが同期ロックを追加し、次のコードを実行できます.この場合、インスタンスは最初のスレッドによって作成されているため、2番目のスレッドはインスタンスを繰り返し作成しません.しかし、ロックは時間のかかる操作であり、できるだけ避けるべきです.
(3)解法3:同期ロック前後2回の判定例が存在するか否か
インスタンスが作成されない前にロック操作が必要で、1つのスレッドだけがインスタンスを作成することを保証します.インスタンスが作成されると、ロック操作は必要ありません.コードは次のように実装されます.
Singleton 3ではinstanceがNULLで作成されていない場合のみ、ロック操作が必要です.Instanceが作成されている場合は、ロックをかける必要はありません.初回のみinstanceがNULLであるため、Singleton 2よりもSingleton 3の時間効率が良いように、インスタンスを初めて作成しようとする場合にのみロックが必要となる.
githubホームページ:https://github.com/chenyufeng1991 .ようこそ!
(1)解法一:単一スレッド環境にのみ適用
インスタンスを1つしか生成できないことが要求されるため、コンストラクション関数をプライベート関数に設定して、インスタンスの作成を禁止する必要があります.静的インスタンスを定義し、必要に応じてインスタンスを作成できます.
public class Singleton1{
private Singleton1(){
}
private static Singleton1 instance = NULL;
public static Singleton1 funcInstance{
get{
if(instance == NULL){
instance = new Singleton1();
}
return instance;
}
}
}
上記のコードはSingleton 1の静的メソッドfuncInstance()では、instanceがnullの場合にのみインスタンスを作成して重複作成を回避し、コンストラクション関数をプライベート関数として定義することで、インスタンスが1つしか作成されないことを保証します.
(2)解法2:マルチスレッド環境では機能するが効率が悪い
解法1のコードは,単一スレッドの場合は正常に動作するが,マルチスレッドの場合は問題がある.2つのスレッドがinstanceがnullであるかどうかを判断するif文まで同時に実行され、instanceが実際に作成されていないと仮定すると、2つのスレッドはインスタンスを作成し、単一のモードの要件を満たさなくなります.
マルチスレッド環境でタイプのインスタンスしか得られないことを保証するには、同期ロックを追加する必要があります.次のようになります.
public class Singleton2{
private Singleton2(){
}
private static readonly object syncObj = new object();
private static Singleton2 instance = NULL;
public static Singleton2 funcInstance{
get{
lock(sync){
if(instance == NULL){
instance = new Singleton2();
}
}
return instance;
}
}
}
2つのスレッドが同時にインスタンスを作成したいと仮定します.同期ロックは、1つの時点で1つのスレッドしか得られないため、1つ目のスレッドがロックされると、2つ目のスレッドは待つしかありません.最初のスレッドがインスタンスがまだ作成されていないことを発見したとき、彼はインスタンスを作成しました.次に、最初のスレッドが同期ロックを解放し、2番目のスレッドが同期ロックを追加し、次のコードを実行できます.この場合、インスタンスは最初のスレッドによって作成されているため、2番目のスレッドはインスタンスを繰り返し作成しません.しかし、ロックは時間のかかる操作であり、できるだけ避けるべきです.
(3)解法3:同期ロック前後2回の判定例が存在するか否か
インスタンスが作成されない前にロック操作が必要で、1つのスレッドだけがインスタンスを作成することを保証します.インスタンスが作成されると、ロック操作は必要ありません.コードは次のように実装されます.
public class Singleton3{
private Singleton3(){
}
private static readonly object syncObj = new object();
private static Singleton3 instance = NULL;
public static Singleton3 funcInstance{
get{
if(instance == NULL){
lock(sync){
if(instance == NULL){
instance = new Singleton3();
}
}
}
return instance;
}
}
}
Singleton 3ではinstanceがNULLで作成されていない場合のみ、ロック操作が必要です.Instanceが作成されている場合は、ロックをかける必要はありません.初回のみinstanceがNULLであるため、Singleton 2よりもSingleton 3の時間効率が良いように、インスタンスを初めて作成しようとする場合にのみロックが必要となる.
githubホームページ:https://github.com/chenyufeng1991 .ようこそ!