singletonの生成 – プログラミング – Home

通知
すべてクリア

[解決済] singletonの生成


tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
Topic starter  

WinNTsp6, VC++5sp3という環境です。

とあるsingleton classをこんな感じで作ったのですが、2ヶ所でGetInstance()してみた
ところ、それぞれのポインタには異なる値が入っている「ことがある」、という現象が起
きて困っています。

class CTib
{
public:
static CSystemMonitor* GetInstance();
private:
static CTib *m_pcTib;
}

CTib* CTib::GetInstance()
{
if( m_pcTib==NULL )
{
m_pcTib = new CTib;
}
return m_pcTib;
}

調べてみたところ、どうやらGetInstance()を呼ぶ2ヶ所というのがそれぞれ別のスレッド
から「ほぼ同時」に呼んでいて、先着分のnew処理が終わらぬうちに後着分のif文に到達
してしまうために後着分でもnewが呼ばれてしまうようなのです。

どちらのスレッドが先に呼ぶという保証はないので、呼び側でsleepさせて時間差を作る
という手法は適切ではないと考えています。CTibを確実にsingletonとして機能させる方
法はないでしょうか。

以上、よろしくお願いいたします。


引用未解決
トピックタグ
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
Topic starter  

あわわ....置換漏れ。
class CTib
{
public:
static CTib* GetInstance();
private:
static CTib *m_pcTib;
}

が正しいです。


返信引用
kumo
 kumo
(@kumo)
ゲスト
結合: 22年前
投稿: 14
 

クリティカルセクションを使うといいです。


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
Topic starter  

>クリティカルセクションを使うといいです。
アドバイスありがとうございます。こんな風にしてみました。

------------------------ tib.h
class CTib
{
public:
static CTib* GetInstance();
private:
static CTib *m_pcTib;
}

------------------------ tib.cpp
static CRITICAL_SECTION cs;
CTib* CTib::GetInstance()
{
EnterCriticalSection( &cs );
if( m_pcTib==NULL )
{
m_pcTib = new CTib;
}
LeaveCriticalSection( &cs );
return m_pcTib;
}

で、この場合、InitializeCriticalSection()はどこで呼べばいいのでしょうか。
GetInstance()の先頭でflagを用意して初期化済みかどうかを見るのでは結局冒頭に挙げ
たのと同じ問題が起きると思うのですが。


返信引用
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 23年前
投稿: 196
 

>で、この場合、InitializeCriticalSection()はどこで呼べばいいのでしょうか。

・グローバルスコープ
・main() の中、スレッドが起動される前

とか。


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

CCriticalSectionではだめ?

あと、直接関係ないけど、この例はダブルチェッキングロックパターンにすると
パフォーマンスがちょっとあがって幸せかも。


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
Topic starter  

テストに手間取っていましたが、CriticalSectionで使用に耐えうる物が実現できまし
た。アドバイスありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました