2016-04-07 6 views
0

Ich habe ein gemeinsames Problem (das hier in mehreren Variationen veröffentlicht wurde) eines Prozesses mit mehreren Threads, die jeweils lesen oder schreiben in eine Gruppe von gemeinsamen Variablen (für die Einfachheit - sagen wir es ist eine einzelne Variable).Design thread sichere Variable Klasse in C++

Jede Variable sollte gegen paralleles Schreiben geschützt sein und paralleles Lesen ermöglichen.

Ich habe mehrere Lösungen gesehen, und entschied sich für die folgenden ein zu konzentrieren, die Wachen (erwähnt in diesem link)

jedoch verwendet, ich konnte nicht die folgenden Grundsätze herauszufinden:

  1. MutexGuard-Klasse: sollte nicht als Singleton implementiert werden. Andernfalls erstellt jeder Thread einen neuen Mutex, der auf einen einzelnen allgemeinen Mutex wartet.

  2. Wenn die Klasse MutexGuard nicht singleTon ist, sollte zumindest der m_Mutex statisch sein, damit er für alle Instanzen dieser Klasse freigegeben wird.

  3. Warum sind Funktion1 und Funktion2 als statisch definiert. Auf diese Weise kann es ohne den Kontext einer Instanz aufgerufen werden (Klasse ist nur Namespace) und der Wert von m_SharedVar fehlt möglicherweise.

  4. Gibt es eine einfache Möglichkeit, die Implementierung für Multi-Leser/Einzelschreiber-Sperre zu ändern? sollte ich in diesem fall nur den mutex typ ändern?

    class MutexGuard { 
        MutexType & m_Mutex; 
        public: 
    
        inline MutexGuard(MutexType & mutex) : m_Mutex(mutex) { 
         m_Mutex.lock(); 
        }; 
    
        inline ~MutexGuard() { 
         m_Mutex.unlock(); 
        }; 
    } 
    
    class TestClass { 
        MutexType m_Mutex; 
        double m_SharedVar; 
    
        public: 
        TestClass() : m_SharedVar(4.0) { } 
        static void Function1() { 
         MutexGuard scopedLock(m_Mutex); //lock the mutex 
         m_SharedVar+= 2345; 
         //mutex automatically unlocked 
        } 
        static void Function2() { 
         MutexGuard scopedLock(m_Mutex); //lock the mutex 
         m_SharedVar*= 234; 
         throw std::runtime_error("Mutex automatically unlocked"); 
        } 
    } 
    
+0

* Jede Variable sollte gegen paralleles Schreiben geschützt sein und paralleles Lesen ermöglichen. * - seien Sie vorsichtig, solange ein Thread schreiben kann, müssen Sie gleichzeitige Lesevorgänge synchronisieren, um Datenrennen zu verhindern. –

+1

Der Code ist inkonsistent: Wenn 'Function1' und -'2'' static' sind, können Sie nicht auf nicht-static-Membervariablen wie 'm_SharedVar' zugreifen. Sie sollten nicht "statisch" sein, es sei denn, m_SharedVar ist auch "statisch". Beginne grundsätzlich damit, darüber nachzudenken, ob deine Daten "statisch" sein sollen oder nicht (wir können es dir nicht sagen), dann mach den "Mutex", der es schützt, gleich. Bei gleichzeitigen Lesern wechseln Sie zu einer Lese-Schreibsperre (die eine neue API und Änderungen an Ihrem Code beinhaltet, um zu sagen, ob Lese- oder Schreibzugriff erforderlich ist); siehe [hier] (http://stackoverflow.com/questions/16774469/a-rw-lock-for-c11-threads). –

+0

@TonyD, danke für die Antwort, genau das habe ich mir gedacht. Ich kopierte diese Lösung aus der Link-Erwähnung in meiner Frage, und ich fand heraus, dass es ein Problem mit der statischen Funktionsdefinition gibt. Allerdings bin ich mir immer noch nicht sicher, ob ich die Klasse Singleton machen muss oder nicht. – Zohar81

Antwort

2

Ich denke, das Problem ist hier die TestClass. Wie von @TonyD richtig ausgeführt, sollte die Implementierung von MutexGuard nicht an Singleton gebunden sein, es sei denn, dies ist explizit erforderlich. Die Absicht von MutexGuard ist, lock() & unlock() des gegebenen Mutex automatisch für den Anrufer durchzuführen. So muss der Aufrufer von MutexGuard nicht explizit lock() oder unlock().

Jetzt ist es die Verantwortung von TestClass, den Mutex vor Mehrfachzugriff zu schützen. In der Regel werden alle Worker-Threads, die die Funktionen von TestClass verwenden, automatisch geschützt, wenn jede Funktion den Mutex sperrt, der für die Instanz der Klasse freigegeben ist. Wiederum ist es implementierungsspezifisch. Dort kann man statische Mutex für alle Fälle geben, oder es können mehrere mutexes für verschiedene gemeinsam genutzte Ressourcen richtet usw.

kommen nun zu Ihrer Frage von

ist es eine einfache Möglichkeit, die Umsetzung für multi- zu ändern Leser/ Einzel Schriftsteller Schloss? sollte ich nur den Mutex-Typ in diesem Fall ändern?

Sie müssen verstehen, dass mehrere Leser/Single-Write ist ein Mythos. Es garantiert keine Parallelität. Es bedeutet nur, dass das Sperren/Entsperren je nach Bedarf schneller wird. Wenn einige das Datum nicht schreiben, können mehrere Leser die Daten lesen (unter der Annahme, dass der Wert nicht geändert wird). In diesem Fall möchten Sie möglicherweise etwas implementieren, das als reader-writer Lock bekannt ist.

Mein Professor nennen immer mutex Schlösser als Fett Schlösser. Es unterscheidet nicht wirklich zwischen Lesen und Schreiben und hat immer eine konstante Sperrzeit, unabhängig von der Arbeit, die Sie auf der freigegebenen Ressource ausführen möchten.

Weitere Informationen finden Sie unter this stackoverflow post. Oder Sie können auch fertige BOOST reader-writer Schlösser verwenden.

+0

Schöne Antwort. One Nitpick: * "Mehrere Leser/Single Write [r] ist ein Mythos" * - der Begriff ist in der Regel zu kommunizieren, dass mehrere Leser *** oder *** ein einziger Schriftsteller zu jedem Zeitpunkt aktiv sein kann - ein nuancierterer Begriff für das, was Sie lieber Leser-Schreiber-Sperren nennen. Vielleicht, wenn Sie mit "/" geschrieben haben, könnte es * missverstanden * bedeuten, eine Sperre zu haben, die mehrere Leser *** und einen einzigen Schreiber gleichzeitig erlaubt - Sie verstehen, dass Sie dieses Missverständnis entlarven. –

+0

Ich stimme @TonyD zu :-) –

Verwandte Themen