2012-02-14 4 views
3

私はC++のオブジェクトでmutexを使う方法を理解しようとしています。オブジェクトとのmutexes

struct Rope{ 
    int n, steps, offset; 
    //std::mutex mut; 

    Rope() {} 
    Rope(int n, int steps, int offset) : n(n), steps(steps), offset(offset) {} 

    void compute(){ 
    double a[n]; 
    for (int i=0; i<n; i++) 
     a[i] = i + offset; 
    for (int step=0; step<steps; step++) 
     for (int i=0; i<n; i++) 
    a[i] = sin(a[i]); 
    } 

}; 

void runTest(){ 
    int numRuns = 30; 
    int n = 10000; 
    int steps = 10000; 

    std::vector<Rope> ropes; 
    std::vector<std::thread> threads; 
    for (int i=0; i<numRuns; i++) 
    ropes.push_back(Rope(n, steps, i)); 
    for (auto& r : ropes) 
    threads.push_back(std::thread(&Rope::compute, r)); 
    for (std::thread& t : threads) 
    t.join(); 
}  

コードがあるとして正常に動作し、私の4コアマシン上〜4倍のスピードアップを見ている:私はスピードテストとして使用しています以下の(ささい)マルチスレッドコードを持っています。私はもちろん、ロープに何も格納していないので、ミューテックスの必要はありません。私が保護する必要があるデータがあると仮定した場合、Ropeにmutexを付けて(例えば)compute()ループ内のstd :: lock_guardを呼び出したいと思います。しかし、ミューテックスのコメントを外すと、割り当てやコピーの演算子に「削除された関数の使用」に関するコンパイラエラーが発生します。オブジェクトを安全にロックする目的で私は何が欠けていますか?

答えて

6

クラスのスレッドセーフを作るための簡単な方法は、問題は、このクラスはコピー不能なることですmutex属性を追加し、

アクセサメソッドで

class cMyClass { 
    boost::mutex myMutex; 
    cSomeClass A; 
public: 
    cSomeClass getA() { 
    boost::mutex::scoped_lock lock(myMutex); 
    return A; 
    } 
}; 
をミューテックスをロックすることです。特に、クラスのオブジェクトをコンテナに格納する場合は、これが重要です。

私はミューテックスを静的にすることで動作させることができます。

class cMyClass { 
    static boost::mutex myMutex; 
    cSomeClass A; 
public: 
    cSomeClass getA() { 
    boost::mutex::scoped_lock lock(myMutex); 
    return A; 
    } 
}; 

しかし、これは、それら全てが同じミューテックスを共有するためのクラス・ブロックのすべてのインスタンスが他のインスタンスは、アクセスしているときことを意味します。

理論的には、静的ではないミューテックスを含むクラスは、コピーコンストラクタと代入演算子を手動でコーディングして、ミューテックスを除外することによってコピー可能にすることができます。しかし、これは、特に開発中に頻繁に変更される多数の属性を持つクラスの場合、適切に行うのは難しく退屈です。

ブロックされているクラスのすべてのインスタンスへのアクセスをブロックする静的なミューテックスが許容できない場合は、クラスの外部にあるmutexを維持するのが最も簡単で簡単な方法です。このようにクラスの内部の仕組みを公開するのは残念なことですが、代わりがより複雑で信頼性が低いので、クラスにアクセスするコードのレベルでmutexが処理されると、かなりの最適化が頻繁に行われます。

+0

@MikeSeymour彼が話していることを誤解していない限り、彼はすべてのスレッドで**同じ**ミューテックスを使用する必要があります。移動セマンティクスを使用してコンテナに配置することは機能しません。 (一方で、現在書かれているように、各スレッドは独自の 'Rope'オブジェクトを取得するので、ミューテックスは必要ありません。問題が明確に説明されていないときに、正しい解決策が何であるかを言うのは難しいです。) –

+0

@ Mike Seymour: 'std :: mutex'は動かない。 'Rope'はデフォルトで' Rope'コンストラクタの 'std :: mutex'を構築することで移動またはコピー可能にすることができます。または、ジェームズが示唆するようにミューテックスを静的にすることによって、どちらのアプローチが適切かは、現時点でOPだけが知っているものです。 –

+0

私の間違い;私は投稿する前に私の前提をチェックしておくべきだった。 –

0

mutexはコピーできません。ミューテックスのコピーを作成するには、 とはどういう意味ですか? mutexを取得して解放する場所はで、 同じmutexにアクセスする必要があるので、runTestで定義し、 参照またはポインタで渡す必要があります。

関連する問題