2016-05-26 4 views
2

Hier sind meine Fragen. Ich habe mehrere Threads, die die Attribute einer struture modifizieren, und ich habe einen Thread, der die Struktur liest. Wie kann ich sicher sein, dass der Wert, den ich gerade lese, nicht von anderen Threads geändert wird? In meinem Fall kann ein Attribut nur durch einen Thread geändert werden.Multithread-Datensynchronisation in 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; 
} 

Dann Wie kann ich sicher sein, dass, wenn ich glob lesen, ist es nicht von writer1 und writer2 geändert werden?

+3

'std :: mutex' oder' std :: atomic' – vu1p3n0x

+2

Sie müssen den Zugriff auf den gemeinsamen Status synchronisieren. Zum Beispiel ['std :: mutex'] (http://en.cppreference.com/w/cpp/thread/mutex). –

+2

Sie möchten über [gegenseitiger Ausschluss] lesen (http://en.cppreference.com/w/cpp/thread). –

Antwort

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; 
} 

Dies ist eine einfache Arbeits Lösung für Ihr Problem <atomic> für nicht teilbar Zugang und Schreiboperationen.

+0

Danke. Kann writer2 in Ihrer Lösung, wenn writer1 in attribut a schreibt, gleichzeitig in attribut b schreiben? – yue

+0

ja, es sollte möglich sein, da sie unterschiedliche Speicheradressen sind. – Stephen

0

Verwenden Sie einen Mutex, es ist extrem einfach, sobald Sie Ihren Kopf herumkommen.

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

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

Code-Beispiel: nicht getestet in datarace führen kann und/oder Deadlock

#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; 
} 

so wird dies die mutex verriegeln, wenn glob ändern und den Mutex entsperren wenn es fertig ist, sich zu verändern. Wenn der Mutex gesperrt ist, kann ein anderer Thread, der versucht, auf diesen Mutex zuzugreifen, dies nicht tun, wird also ein wenig warten und es dann erneut versuchen. schließlich wird es es fangen und in der Lage sein, es selbst zu sperren. Dann muss der andere Thread darauf warten, dass er entsperrt wird.

Der lock_guard, den ich verlinkt habe, ist eine sicherere Möglichkeit, deinen Mutex zu verwenden, funktioniert aber nur in Funktionen. Sie setzen es am Anfang einer Funktion und bleiben dann gesperrt, bis die Funktion zurückkehrt. Dies bedeutet, dass Sie nicht sicherstellen müssen, dass Sie den Mutex für jeden Rückpfad der Funktion entsperren, da dies automatisch erfolgt.

Mutex's haben ein Problem mit Deadlocks. Dies passiert, wenn Sie einen Mutex sperren und dann versuchen, den Mutex erneut im selben Thread zu sperren, bevor der Mutex entsperrt wurde. Es wird dann ewig warten, kann nicht entsperrt werden, und die anderen Threads können auch nicht fortgesetzt werden. Eine einfache Lösung besteht darin, mehrere Mutexe zu verwenden, wenn Sie Funktionen aus einem Mutex-Bereich aufrufen.