2016-05-25 2 views
1

Laut Herb Sutter (http://isocpp.org/blog/2012/12/you-dont-know-const-and-mutable-herb-sutter) dürfen in C++ 11 const-Methoden das Objekt nicht bitweise ändern oder müssen eine interne Synchronisation durchführen (z. B. mit einem Mutex), wenn sie veränderliche Datenelemente haben.Wenn C++ konstante Methoden den veränderbaren Zustand synchronisieren, müssen auch nichtkonstante Methoden dies tun?

Meine Frage ist, müssen nicht-const Methoden den Mutex auch erwerben? Oder können sie sich auf die externe Synchronisierung verlassen, die ihr Benutzer ausführen muss, wenn der Benutzer gleichzeitig konstante und nicht konstante Methoden für dasselbe Objekt mischen will?

EDIT: Anders gesagt, ist die folgende Klasse Thread-Safe? bietet die folgende Klasse Sutters "grundlegende Thread-Sicherheitsgarantie" (von part 4b of GOTW #95)?

#include <thread> 

class C { 
    public: 
    void const_method() const 
    { 
    std::lock_guard<std::mutex> g(m); 
    i = 2; 
    } 

    void non_const_method() 
    { 
    // std::lock_guard<std::mutex> g(m); // <-- is this needed? 
    i = 1; 
    } 

    private: 
    mutable int i; 
    mutable std::mutex m; 
}; 

Antwort

4

Nein, Ihre Klasse ist nicht an und für sich Thread-sicher.

void non_const_method() 
{ 
    // std::lock_guard<std::mutex> g(m); // <-- is this needed? 
    i = 1; 
} 

obige ist nicht sicher, wie Gewinde mehrere Threads somit die Funktion aufrufen könnte i gleichzeitig zu verändern.

So zu beantworten:

hat die folgende Klasse bieten Sutters „Grundfaden Sicherheitsgarantie“

Dann ja, die Klasse stellt eine „Grundfadensicherheitsgarantie“. Sie können keine Instanz von einer anderen Instanz ändern, und die Methoden const der Klasse sind Thread-sicher.

Sie müssen eine Art externe Synchronisation verwenden, um die veränderbaren Funktionen der Klasse für dieselbe Instanz in mehreren Threads zu verwenden, aber Ihre nicht veränderbare Funktion erfordert keine externe Synchronisation.

+0

Wie könnten mehrere Threads gleichzeitig "i" ändern? Die einzige Funktion, die rechtlich gleichzeitig aufgerufen werden kann, ist "const_method", und sie erhält eine Sperre. (Code, der 'non_const_method' gleichzeitig aufruft, wäre nicht Thread-sicher, aber es gibt keinen solchen Code in der Klasse.) –

+1

@DavidSchwartz:" * Die einzige Funktion, die gleichzeitig gleichzeitig aufgerufen werden kann, ist const_method, * "Und deshalb Die Klasse ist nicht threadsicher. Der Punkt, den Herb macht, ist, dass "konstante" Methoden immer threadsicher sein sollten.Nicht-konstante Methoden können Thread-sicher sein oder auch nicht, abhängig von den Launen des Klassenimplementierers. Die Verwendung von 'const'-Methoden threadsicher bedeutet nicht, dass der gesamte Typ threadsicher ist (es sei denn, seine einzigen Verwendungen verwenden' const'-Methoden). –

+0

@NicolBolas Es bedeutet, dass der gesamte Typ Thread-sicher ist, solange nicht zwei nicht konstante Methoden der gleichen Instanz der Klasse gleichzeitig aufgerufen werden. Aber dann wäre es der Code, der die beiden nichtkonstanten Methoden zur gleichen Zeit aufgerufen hat, die nicht Thread-sicher waren, nicht die Klasse. Eine Klasse ist threadsicher, wenn sie vorhersehbares Verhalten bietet, wenn sie in Multithread-Code verwendet wird, der nicht gegen den Schnittstellenvertrag verstößt. Der übliche Schnittstellenvertrag ist "keine gleichzeitigen Zugriffe auf nicht-konstante Methoden auf derselben Instanz". Jede Klasse macht schlechte Sachen, wenn Sie ihren Schnittstellenvertrag verletzen. –

0

Idealerweise muss ein Schreiber eine strengere Sperre erhalten als ein Leser würde. Sie könnten argumentiert haben, wenn der Leser eine Sperre erhalten muss oder nicht (aber Sie haben anders gefragt). Writer sind mehr der Grund, Dateninkonsistenz zu erzeugen.

Mit strikter Sperre, meine ich in einem Locking-Protokoll, wo Reader-Lock und Writer-Lock möglich sind - dann Writer-Sperre wäre strenger. In den meisten Implementierungen würde ein Thread, der eine Schreibsperre erhält, alle anderen Threads daran hindern, irgendeine Art von Sperre zu erhalten, aber Lesersperren können gleichzeitig ausgeführt werden. Eine non-const-Funktion würde also idealerweise eine Writer-Lock-Funktion übernehmen, aber const kann einfach eine Reader-Lock-Funktion übernehmen - und somit die parallele Ausführung derselben Funktion (oder ähnlicher Funktionen desselben Objekts) ermöglichen.

Ja, es ist möglich, dass ein Verriegelungs-Protokoll wird nicht bevorzugt Threads warten, über reader Fäden Warten writer geben. Aber das ist Implementierungsdetail.