4

次のようなプロパティがあります。

private:
Foo* myFoo_m;

public:
Foo getMyFoo() const
{
    if (myFoo_m == NULL)
    {
       myFoo_m = new Foo();
       // perform initialization

これはシングルスレッド環境ではうまく機能しますが、マルチスレッド環境ではどのように処理すればよいでしょうか? 私が見つけた情報のほとんどは静的シングルトンを扱っていますが、この場合、myFoo はパブリック インスタンス プロパティです。

これを C# (Lazy を使用できる) と Java (ダブル チェック ロックを使用できる) から移植していますが、C++ でこれを行う簡単な方法はないようです。外部ライブラリ (BOOST なし) に頼ることはできません。これは Windows と Linux で動作する必要があります。C++11も使えません。

どんな洞察でも良いでしょう。私はC++が初めてです。

4

3 に答える 3

5

C++11にアクセスできる場合は、ロックを使用std::mutexして、複数のスレッドが遅延セクションを初期化するのを防ぐことができます。(注: std::mutexVS2012 を搭載した Windows でのみ利用可能になりました)

次のコマンドを使用して、ミューテックスのスコープ付き取得を実行することもできますstd::lock_guard

private:

std::mutex m_init_mutex;

public:

Foo getMyFoo() const
{
    {
       std::lock_guard<std::mutex> lock(m_init_mutex);
       if (myFoo_m == NULL)
       {
          myFoo_m = new Foo();
          // perform initialization
       }
    }

編集:OPはC++ 11はオプションではないと述べましたが、おそらくこの答えは将来役立つでしょう

于 2012-11-02T15:59:32.517 に答える
4

「C++11 なし」、「Boost やその他のサードパーティ コードなし」、「Windows と Linux で動作する必要がある」と言うと、実装固有のロック メカニズムの使用に制限されます。

最良の選択肢は、自分用に単純なロック クラスを定義し、Linux では pthread_mutex を、Windows では CriticalSection を使用するように実装することだと思います。そもそもスレッドを開始するための、プラットフォーム固有のコードが既にある可能性があります。

Windows Services for UNIX のようなものを試して、プラットフォーム固有のコードを書かないようにすることもできますが、おそらく 1 つのロックには価値がありません。これは Microsoft によって提供されていますが、外部ライブラリと見なすこともできます。

于 2012-11-02T16:15:13.633 に答える
1

警告:「C++11 なし」の要件が見当たらなかったので、回答を無視してください。


C++11 では、静的変数の初期化をスレッドセーフにすることが義務付けられているため、「ごまかす」と考えられる簡単な方法を次に示します。

Foo init_foo()
{
    // initialize and return a Foo
}

Foo & get_instance_lazily()
{
    static Foo impl = init_foo();
    return impl;
}

インスタンスは、最初に を呼び出したときに初期化され、get_instance_lazily()スレッドセーフに初期化されます。

于 2012-11-02T16:07:20.973 に答える