squirrel_code @ ウィキ

singleton × thread

最終更新:

squirrel_code

- view
管理者のみ編集可

singleton × thread

last update: 2010/12/28 (Tue)

さて,この記事のテーマとは singleton と thread でどちらが攻めでどちらが○けか,ではない!

なんてタイトルをつけやがる….期待させて申し訳ないが(ありえない) Singleton とは,プログラム内でインスタンスが 1 つしか存在しないことを保証するクラスのこと. 要はグローバル変数の代わり.簡単なコードは以下の通り.

// singleton.h
#include <iostream>
#include <boost/thread.hpp>

class Singleton
{
private:
    Singleton() {
        std::cout << "Singleton : created" << std::endl;
    }
    Singleton(const Singleton&);            // コピー禁止
    Singleton& operator=(const Singleton&); // 代入禁止
public:
    ~Singleton() {
        std::cout << "Singleton : deleted" << std::endl;
    }
    // インスタンス取得関数
    static Singleton* getInstance();
};

// singleton.cpp
#include "singleton.h"

Singleton* Singleton::getInstance()
{
    static Singleton instance;
    return &instance;
}

さてここで疑問に思った.このインスタンス取得関数ってマルチスレッド安全なの?

調べると,「C では静的自動変数の初期化は,実行フローが最初に変数の宣言・初期化行を通過した時に行われる」とある.ならば Singleton のコンストラクタが何やら時間のかかる処理をやるとして,あるスレッドが Singleton のコンストラクタにいる間に他のスレッドがインスタンス取得関数を呼んだらどうなるんだろう.

てことで実験.

// singleton.h
#include <iostream>
#include <boost/thread.hpp>

class Singleton
{
private:
    Singleton() {
        // 1000 ミリ秒かかる処理
        boost::thread::sleep(
           boost::get_system_time()
               + boost::posix_time::milliseconds(1000));
        std::cout << "Singleton : created" << std::endl;
    }
    Singleton(const Singleton&);            // コピー禁止
    Singleton& operator=(const Singleton&); // 代入禁止
public:
    ~Singleton() {
        std::cout << "Singleton : deleted" << std::endl;
    }
    // インスタンス取得関数
    static Singleton* getInstance();
};

// singleton.cpp
#include "singleton.h"
#include <cstdlib>

Singleton* Singleton::getInstance()
{
    static Singleton instance;
    return &instance;
}

void func()
{
    std::cout << "func : begin" << std::endl;
    // インスタンス取得関数の呼び出し
    Singleton* singleton = Singleton::getInstance();
    std::cout << "func : end" << std::endl;
}

int main(int argc, char* argv[])
{
    boost::thread th1( &func );
    boost::thread th2( &func );
    boost::thread th3( &func );
    
    th1.join();
    th2.join();
    th3.join();

    return EXIT_SUCCESS;
}

結果.

func : begin
func : begin
func : begin
Singleton : created # この直前で1秒固まる
func : end
func : end
func : end
Singleton : deleted

マルチスレッド安全でした*1.なんだつまらん(笑)

&trackback()

参考



コメント

  • コメントの投稿テスト -- (tossy_squirrel) 2010-12-29 03:35:18
名前:
コメント:

すべてのコメントを見る


関連ページ



関連ブログ

#blogsearch
記事メニュー
人気記事ランキング
目安箱バナー
注釈

*1 あくまで gcc では.他の処理系では知りません.規格上はどうなってるんだろう…