63
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

スレッドセーフな Singleton クラスを作成する

有名な話であると思っていたが、つい最近嵌った同僚がいたのでメモすることにした。

注)下記内容は Visual C++ / C++11 未対応の g++ を使用している場合の話です

Singleton パターン

デザインパターンの一つ。あるクラスが一つのインスタンスしか持たないことを確実にしたい時に使用する。C++ での Singleton パターンの実装例は下記の通り。

// Singleton.h
#pragma once

class Singleton
{
    public:
        static Singleton &getInstance();
    private:
        Singleton(){}
        Singleton(const Singleton &other){}
        Singleton &operator=(const Singleton &other){}
};
// Singleton.cpp
#include "Singleton.h"

Singleton &Singleton::getInstance() {
    static Singleton instance;
    return instance;
}
// main.cpp
#include <iostream>
#include "Singleton.h"

int main()
{
    Singleton &singleton = Singleton::getInstance();
    // do something...
    return 0;
}

上記実装の問題点

Visual C++ / C++11 未対応の g++ を使用している場合、 上で示した実装にはスレッドセーフでないという問題がある。
例えば二つのスレッドが同時に Singleton::getInstance() を呼び出した場合、

  • Singleton インスタンスが二回作成される
  • 一方のスレッドで完全に初期化される前にもう片方のスレッドで Singleton インスタンスが使用される

のいずれかの問題が発生する可能性がある。

解決策 1 : 静的な初期化を行う

プログラムがまだシングルスレッドであると想定できる main() の前で Singleton クラスのインスタンスを作成すれば良い。静的な初期化を行うためには、下記コードを Singleton.cpp に追加すれば良い。

// Singleton.cpp
// 上で示した部分は省略
static Singleton &singleton = Singleton::getInstance();

解決策 2 : Singleton クラスの初期化ルーチンを追加する

例えば下記 init() の様な、Singleton クラス用に初期化ルーチンを追加する。
なお下記コードは C++11 のものであり、 C++11 以前の C++ を使用している場合、ミューテックスロックを行う処理は自作 (または他のライブラリを利用) する必要がある。

#include <mutex>

static std::mutex s_mutex;
void init() {
    std::lock_guard<std::mutex> lock(s_mutex);
    Singleton::getInstance();
}

解決策 3 : コンパイルオプション -fthreadsafe-statics を明示する

$ g++ -fthreadsafe-statics main.cpp Singleton.cpp

まとめ

スレッドセーフな Singleton クラスを作成するには

  • 静的な初期化
  • 初期化ルーチンの追加
  • コンパイルオプション -fthreadsafe-statics を明示する

などの方法が有効である。
なお、本問題を解決する方法を調べると DCLP (ダブルチェックロッキングパターン) という方法に出くわすと思う。
しかし DCLP は全てのコンパイラで確実に機能する保証は無いらしく、使用しない方が良いと思う。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
63
Help us understand the problem. What are the problem?