2

MSVC 2012 で次のコードを実行すると、3 行目と 8 行目にブレークポイントが設定されます。

最初の休憩は 8 行目にあります。

lock_guard は正常に呼び出され、3 行目で中断します。今回は、ロックが既に取得されているため、ステップ オーバーすると例外がスローされます。

それはまだ同じスレッド呼び出しであるため、私は本当にそれが先に進むことを望んでいます (11 行目から来たばかりです)。

このシナリオにより適した別のロック メカニズムはありますか?

私はネイティブの win32 プログラミングのバックグラウンドを持っているので、WaitForSingleObject には慣れています。

私は例外を処理することになっていますか?私が見た例のどれも、lock_guard の例外ハンドラーを持っていません...

一度に複数のスレッドがマップにアクセスしないようにするためのより良い方法はありますか? 書き込みと読み取りの両方のロックが必要ですが、ReleaseMutex を使用する必要がないため、lock_guard はスムーズな代替手段のように思えました...

    //Cars.h
    mutable std::mutex carsMutex;
    class Cars
    {
    private:
        std::map<std::string,Cars> _cars;
    public:
        virtual ~Cars() {}
        Cars() {}
        Cars & operator[](const std::string &key);
        Cars & operator[](const DWORD &key);
        std::string color;
    };

    //Cars.cpp
      #include "Cars.h"
1.    Cars & Cars::operator[](const std::string &key)
2.    {
3.        std::lock_guard<std::mutex> lock_a(carsMutex);
4.        return _cars[key];
5.    }
6.    Cars & Cars::operator[](const DWORD &key)
7.    {
8.        std::lock_guard<std::mutex> lock_a(carsMutex);
9.        std::stringstream ss;
10.       ss << key;
11.       return operator[](ss.str());
12.   }
14.   void main()
15.   {
16.       //ok i have multiple threads like this one writing and reading from the map
17.       Cars cars;
18.       cars[(DWORD)2012]["volvo"].color = "blue";
19.   }

更新: 上記のコードを編集したものを次に示します。私は答えを考慮しました。これは std::lock_guard を正しく使用するための私の新しい試みです。正しくない場合はコメントしてください。

    //Cars.h
    mutable std::recursive_mutex carsMutex;
    class Cars
    {
    private:
        std::string _color;
        std::map<std::string,Cars> _cars;
    public:
        virtual ~Cars() {}
        Cars() {}
        Cars & operator[](const std::string &key);
        Cars & operator[](const DWORD &key);
        void color(const std::string &color);
        std::string color();
    };

       //Cars.cpp
       #include "Cars.h"
 1.    Cars & Cars::operator[](const std::string &key)
 2.    {
 3.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
 4.        return _cars[key];
 5.    }
 6.    Cars & Cars::operator[](const DWORD &key)
 7.    {
 8.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
 9.        std::stringstream ss;
10.        ss << key;
11.        return operator[](ss.str());
12.    }
13.    void color(const std::string &color)
14.    {
15.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
16.        _color = color;
17.    }
18.    std::string color()
19.    {
20.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
21.        return _color;
22.    }
23.
24.    Cars cars;//this is global...
25.    void main()
26.    {
27.        //ok i have multiple threads like this one writing and reading from the map
28.        cars[(DWORD)2012]["volvo"].color("blue");
29.    }
4

1 に答える 1

4

スレッドが既に持っているミューテックスを再取得できるようにするにstd::recursive_mutexは、std::mutex.

ただし、より大きな問題があります。マップ要素の割り当てに使用する参照を返す前に、アクセサーがミューテックスのロックを解除しているため、割り当て自体が保護されていません。これは、戻る前に代入を行う「セッター」関数を作成することで修正できます。または、デストラクタで解放されたミューテックス ロックを含むプロキシ オブジェクトを返すことによって。この問題を解決すると、おそらくrecursive_mutex.

于 2012-08-23T22:35:59.397 に答える