2016-12-05 18 views
0

私は大きなプログラムで何をしようとしているのかを模倣するためにこのサンプルプログラムを書いた。アトミックとミューテックスのクラス内のスレッドC++

ユーザーからのデータがあり、処理のためにスレッドに渡されます。私は、データの周りにミューテックスを使用して、データがあるときにフラグを立てます。

ラムダ式を使用すると、スレッドに送信する*へのポインタですか?私はcoutステートメントで期待した動作を得ているようです。

データの周りにミューテックスが正しく使用されていますか?

アトミックとミューテックスをクラスのプライベートメンバーとして入れてもいいですか?

がfoo.h

#pragma once 
#include <atomic> 
#include <thread> 
#include <vector> 
#include <mutex> 

class Foo 
{ 
public: 
    Foo(); 
    ~Foo(); 

    void StartThread(); 
    void StopThread(); 
    void SendData(); 

private: 
    std::atomic<bool> dataFlag; 
    std::atomic<bool> runBar; 
    void bar(); 
    std::thread t1; 
    std::vector<int> data; 
    std::mutex mx; 
}; 

foo.cの

#include "FooClass.h" 
#include <thread> 
#include <string> 
#include <iostream> 

Foo::Foo() 
{ 
    dataFlag = false; 
} 

Foo::~Foo() 
{ 
    StopThread(); 
} 

void Foo::StartThread() 
{ 
    runBar = true; 
    t1 = std::thread([=] {bar(); }); 
    return; 
} 

void Foo::StopThread() 
{ 
    runBar = false; 

    if(t1.joinable()) 
     t1.join(); 

    return; 
} 

void Foo::SendData() 
{ 
    mx.lock(); 
    for (int i = 0; i < 5; ++i) { 
     data.push_back(i); 
    } 
    mx.unlock(); 
    dataFlag = true; 
} 

void Foo::bar() 
{ 
    while (runBar) 
    { 
     if(dataFlag) 
     { 
      mx.lock(); 
      for(auto it = data.begin(); it < data.end(); ++it) 
      { 
       std::cout << *it << '\n'; 
      } 
      mx.unlock(); 
      dataFlag = false; 
     } 
    } 
} 

main.cppに

#include "FooClass.h" 
#include <iostream> 
#include <string> 

int main() 
{ 
    Foo foo1; 

    std::cout << "Type anything to end thread" << std::endl; 

    foo1.StartThread(); 
    foo1.SendData(); 

    // type something to end threads 
    char a; 
     std::cin >> a; 

    foo1.StopThread(); 

    return 0; 
} 
+1

使用のstd ::手動mx.lockを呼び出すのではなく、をlock_guard()/アンロック() –

+0

例えば、あなたのSendDataは次のようになります'それとも' detach() ' –

+0

@DmitryKatkevichなぜですか?彼は後で 'join()'します... – vu1p3n0x

答えて

0

あなたは、スレッドがRAII技術を使用して接合されていることを確認しますか?チェック。

すべてのデータアクセス/変更は、atomicまたはmutexで保護されていますか?チェック。

ミューテックスロックはstd::lock_guardを使用しますか?いいえ。 std::lock_guardを使用すると、RAIIでlock()unlock()の呼び出しがラップされます。これにより、ロック内で例外が発生しても、ロックが解除されることが保証されます。

アトミックやミューテックスをクラスのプライベートメンバーとして入れてもいいですか?

その良くも悪くも、しかしFooが作業を行い、同期を制御std::threadのラッパーで、このシナリオでは、どちらも、それは理にかなっています。

ラムダ式を使用すると、スレッドに送信する*ポインタへのポインタですか?

はい、さらに明示するためにt1 = std::thread([this]{bar();});を行うこともできます。

ロックの後にdataFlag割り当てを使用すると、問題が発生することがあります。 barが最初のものを処理するようにSendDataを2回呼び出すと、dataFlag = falseを設定する前に停止し、2番目の呼び出しでデータが追加されるようにするには、trueにフラグを設定してfalseに戻します。その後、あなたは "送信"されたデータを持っていますが、barは何も処理していないと思います。

その他のトリッキーな状況があるかもしれませんが、これは単なる例です。それをロックに移動すると、その問題は解消されます。あなたはどちらか `加わるべきスレッドを開始すると)(

void Foo::SendData() 
{ 
    std::lock_guard<std::mutex> guard(mx); 
    for (int i = 0; i < 5; ++i) { 
     data.push_back(i); 
    } 
    dataFlag = true; 
} 
関連する問題