2016-05-26 3 views
2

ここに私の質問があります。私は構築物の属性を変更するいくつかのスレッドを持っており、構造を読んだスレッドがあります。読んでいる値が他のスレッドによって変更されていないことを確認するにはどうすればよいですか?私の場合、属性は1つのスレッドでしか変更できません。C++でのマルチスレッドデータ同期

Exemple:

typedef struct 
{ 
    int a; 
    double b; 

} data; 

data glob; 

int main() 
{ 

    thread reader([]() 
    { 
     while(1) 
     { 
      sleep(1s); 
      cout << glob; 
     } 
    }); 

    thread writer1([]() 
    { 
     while(1) 
      glob.a++; 
    }); 
    thread writer2([]() 
    { 
     while(1) 
      glob.b++; 
    }); 


    int i; 
    cin >>i; 
} 

次に、どのように私は私がグロブを読んだとき、それはwriter1とwriter2によって変更されていないことを確認することができますか?

+3

'std :: mutex'または' std :: atomic' – vu1p3n0x

+2

共有状態へのアクセスを同期させる必要があります。たとえば、['std :: mutex'](http://en.cppreference.com/w/cpp/thread/mutex)などです。 –

+2

あなたは[相互排除](http://en.cppreference.com/w/cpp/thread)について読んでみたいです。 –

答えて

4
#include <thread> 
#include <atomic> 
#include <iostream> 
#include<chrono> 

typedef struct 
{ 
    std::atomic_int a; 
    std::atomic<double> b; 



} data; 



data glob; 


int main() 
{ 
    glob.a.store(0);//store data in the atomic variable 
    glob.b.store(0.0); 

    std::thread reader([]() 
    { 
     while (1) 
     { 
      std::this_thread::sleep_for(std::chrono::seconds(1)); 
      std::cout << glob.a.load() << " " << glob.b.load() << std::endl; //get the value of the variable 
     } 
    }); 

    std::thread writer1([]() 
    { 
     while (1) 
      glob.a++; 
    }); 
    std::thread writer2([]() 
    { 
     while (1) 
      glob.b.store(glob.b.load() +1); // std::atomic<double> has no member operator++ so have to improvise 
    }); 


    int i; 
    std::cin >> i; 
} 

これは、非割り切れアクセスするため<atomic>を使用して、問題の簡単な実用的なソリューションであると書き込み操作。

+0

ありがとうございます。あなたの解決策では、writer1がattributに書き込んでいるとき、writer2は同時にattributrに書き込むことができますか? – yue

+0

はい、異なるメモリアドレスであるため可能です。 – Stephen

0

ミューテックスを使用すると、一度頭を浮かせれば非常に簡単です。

http://en.cppreference.com/w/cpp/thread/mutex

http://en.cppreference.com/w/cpp/thread/lock_guard

コード例:は、データ競合をもたらし、および/またはグロブを変更するときに、これは、ミューテックスをロックする

#include <thread> 
#inclue <mutex> 
typedef struct 
{ 
    int a; 
    double b; 

} data; 

data glob; 
mutex mymutex; 

int main() 
{ 

    thread reader([]() 
    { 
     while(1) 
     { 
      mymutex.lock(); 
      sleep(1s); 
      cout << glob; 
      mymutex.unlock(); 
     } 
    }); 

    thread writer1([]() 
    { 
     while(1) 
      mymutex.lock(); 
      glob.a++; 
      mymutex.unlock(); 
    }); 
    thread writer2([]() 
    { 
     while(1) 
      mymutex.lock(); 
      glob.b++; 
      mymutex.unlock(); 
    }); 


    int i; 
    cin >>i; 
} 

デッドロック、およびミューテックスのロックを解除することができるをテストしていませんそれが変わり終わったら。ミューテックスがロックされている場合、そのミューテックスにアクセスしようとしている別のスレッドはできないため、少し待ってからもう一度やり直してください。最終的にはそれをキャッチして、それ自体をロックすることができます。それから、もう一方のスレッドはロックを解除するのを待たなければなりません。

私がリンクしているlock_guardはあなたのミューテックスを使用するより安全な方法ですが、関数でのみ動作します。関数の先頭に置くと、関数が戻るまでロックされたままになります。これは、自動的に行われるように関数の戻りパスごとにmutexのロックを解除する必要がないことを意味します。

ミューテックスにはデッドロックの問題があります。これは、ミューテックスをロックしてから、同じスレッドでミューテックスをロックしようとすると、ミューテックスのロックが解除される前に発生します。その後、ロックを解除することができず永遠に待機し、他のスレッドも続行できません。 mutexed領域から関数を呼び出す場合は、複数のmutexを使用するのが簡単な方法です。