Delphi: bevorzugte Art des Schutzes mit kritischen Abschnitten

8

Ich habe ein Objekt x, auf das von mehreren (5+ Threads) zugegriffen werden muss. Die Struktur des Objekts ist

%Vor%

Was ist die bessere (eleganteste) Art des Schutzes:

a)

%Vor%

Ende;

und greifen Sie immer auf das Objekt als GetSafeObj (). x: = 3;

oder

%Vor%

Ende;

und greifen Sie immer normal auf das Objekt zu. Ich denke, die erste Option ist eleganter, auch wenn beide Methoden gut funktionieren sollten. Ay Kommentare?

    
Lobuno 12.11.2011, 01:07
quelle

3 Antworten

7

Wählen Sie Option B, um den kritischen Abschnitt intern für das Objekt zu machen. Wenn der Benutzer der Klasse eine externe Funktion verwenden muss, um sicher auf die Instanz zuzugreifen, ist es unvermeidbar, dass jemand nicht wird und das Haus wird fallen.

Sie müssen auch darüber nachdenken, welche betriebliche Semantik Sie vor mehreren gleichzeitigen Lesevorgängen schützen möchten. schreibt. Wenn Sie eine Sperre in Getter und Setter einfügen, können Sie garantieren, dass Ihr Objekt intern kohärent ist, aber Benutzer Ihres Objekts können Multithreading-Artefakte sehen. Wenn beispielsweise Thread A 10 in eine Eigenschaft Ihres Objekts schreibt und Thread B 50 in diese Eigenschaft desselben Objekts schreibt, kann nur eine davon die letzte sein. Wenn A zuerst passiert, dann wird A dies beobachten Sie schrieben eine 10 auf die Eigenschaft, aber wenn sie es wieder lesen, sehen sie B's 50, die sich dort in die Lücke zwischen A's Read-After-Write eingeschlichen haben.

Beachten Sie auch, dass Sie zum Schutz eines einzelnen ganzzahligen Feldes nicht unbedingt eine Sperre benötigen. Ausgerichtete zeigergroße Integer-Schreiboperationen sind heute atomare Operationen auf nahezu jedem Hardwaresystem. Sie benötigen auf jeden Fall eine Sperre, um mehrteilige Daten wie Strukturen oder mehrstufige Operationen wie das gleichzeitige Ändern zweier verwandter Felder zu schützen.

Wenn es irgendeinen Weg gibt, wie Sie Ihr Design überarbeiten können, um diese Objekte lokal für eine bestimmte Operation in einem Thread zu machen, tun Sie es. Das Erstellen von lokalen Kopien von Daten kann Ihren Speicherbedarf leicht erhöhen, aber es kann Ihren Code für Multithreading erheblich vereinfachen und schneller laufen als Mutex-Landminen in der gesamten App zu hinterlassen. Suchen Sie auch nach anderen vereinfachenden Annahmen: Wenn Sie Ihr System so einrichten können, dass das Objekt unveränderlich ist, während es für mehrere Threads verfügbar ist, benötigt das Objekt überhaupt keinen Sperrschutz. Schreibgeschützte Daten können über Threads gemeinsam genutzt werden. Sehr, sehr gut.

    
dthorpe 12.11.2011 01:49
quelle
6

Die CS muss ein Mitglied des Objekts sein und die CS innerhalb der Property-Getter / Setter-Methoden verwenden. Der andere Ansatz funktioniert nicht, da er die CS sperrt und entsperrt, bevor das Objekt tatsächlich verarbeitet wird, sodass der Eigenschaftswert überhaupt nicht geschützt ist.

    
Remy Lebeau 12.11.2011 01:20
quelle
5

Ein einfacher Weg ist ein Thread-sicheres Wrapper um das Objekt, ähnlich wie TThreadList . Der Wrapper benötigt zwei Methoden: Lock (um den kritischen Abschnitt einzugeben und das innere Objekt zurückzugeben) und Unlock (um den kritischen Abschnitt zu verlassen).

    
Ondrej Kelle 12.11.2011 01:29
quelle

Tags und Links