2014-11-20 18 views
5

Ich arbeite mit Threads und das ist der Grund, warum ich Mutexe zum Sperren freigegebener Ressourcen verwenden. Die grundlegende Verwendung von Sperren besteht darin, Ressourcen in Block sperren/entsperren zu setzen.Sperren und entsperren Ressourcen mit einem einzigen Befehl

procedure RefreshData; 
begin  
    DataLock; 
     GetData; 
     GetSettings; 
     CheckValues; 
     ... 
    DataUnlock; 
end; 

Da es immer ein Paar Sperren/Entsperren ist ich über vereinfachte Sperre begann zu denken/Entsperren Ansatz, die Ressourcen automatisch würde entsperren, wenn sie nicht mehr benötigt.

Also war meine Idee, eine neue Prozedur einzuführen, die als Eingabeparameter einen Verweis auf die Prozedur nehmen würde. Dies gibt mir die Möglichkeit, die anonyme Methode zu verwenden.

-Code wäre so etwas wie:

type TBaseProc = reference to procedure; 

procedure TMyObject.LockMethod(AMeth: TBaseProc); 
begin 
    DataLock; 
    try 
    AMeth; 
    finally 
    DataUnlock; 
    end; 
end; 


procedure TForm1.RefreshData; 
begin 
    MyObject.LockMethod(
    procedure 
    begin 
    GetData; 
    GetSettings; 
    CheckValues; 
    ... 
    end; 
); 

end; 

Dieser Ansatz hat einen Sinn oder ist es besser oder noch einfacher Lösung für dieses?

Dank und Grüße.

+0

Mögen Sie die Leistung oder nicht? –

+2

Die einfachste Lösung wäre, wenn der Compiler native Unterstützung für Lock() -Anweisung wie in C# hätte: http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx. Persönlich verwende ich Code-Vorlagen zum Sperren/Entsperren von Paaren. –

+0

@David: Ja, mir ist die Leistung wichtig. Gibt es eine Schätzung, wie viel Overhead diesen Ansatz verursachen könnte? Ich denke, Lock/Unlock-Paar ist immer noch besser Ansatz in Bezug auf die Leistung. – Nix

Antwort

0

Dieser Ansatz ist bei weitem nicht perfekt, weil, wie ich aus Ihrem Code verstanden habe, Sie nur eine Sperre pro gesamte Anwendung haben. Es ist besser, wenn jede unabhängige Dateneinheit ihre eigene Sperre hat. Sie hätten also eine abstrakte Klasse wie diese:

type 
    TAbstractData = class 
    private 
     CriticalSection: TRtlCriticalSection 
    public 
     constructor Create; 
     procedure Lock; 
     procedure Unlock; 
     destructor Destroy; override; 
    end; 

Dann erben Sie andere Klassen aus dieser abstrakten Klasse, die das Sperren implementiert.

Ein CriticalSection ist die effizienteste Synchronisationsklasse, die bisher in Windows implementiert wurde. Es ist praktisch kostenlos - verbraucht fast keine Systemressourcen, es sei denn, es gibt Threadkonflikte, und ruft keinen teuren Kontextwechsel auf, wenn nur ein Thread die Daten verwendet.

Nachdem ich die Antwort eingereicht habe, habe ich einen guten Artikel im Internet gefunden - http://blog.synopse.info/post/2016/01/09/Safe-locks-for-multi-thread-applications - der Autor empfiehlt ähnlichen Ansatz.