2014-11-20 13 views
5

Sto lavorando con thread e questo è il motivo per cui uso mutex per bloccare le risorse condivise. L'utilizzo di base del blocco consiste nel mettere le risorse all'interno del blocco Blocco/sblocco.Blocco e sblocco risorse con comando singolo

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

Perché c'è sempre un paio di blocco/sblocco ho iniziato a pensare di blocco semplificato/sblocco approccio che sarebbe automatico sbloccare queste risorse quando non serve più.

Quindi la mia idea era di introdurre una nuova procedura che avrebbe preso come parametro di input un riferimento alla precedenza. Questo mi darà la possibilità di usare un metodo anonimo.

codice sarebbe qualcosa di simile:

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; 

ha questo approccio alcun senso o c'è o meglio ancora più semplice soluzione a questo?

Grazie e saluti.

+0

Ti interessano le prestazioni o no? –

+2

La soluzione più semplice sarebbe se il compilatore avesse il supporto nativo per l'istruzione Lock() come in C#: http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx. Personalmente utilizzo modelli di codice per coppie di lock/unlock. –

+0

@David: Sì, mi preoccupo delle prestazioni. C'è qualche stima su quanto sovraccarico potrebbe causare questo approccio? Immagino che la coppia Lock/Unlock sia ancora un approccio migliore in termini di prestazioni. – Nix

risposta

0

Questo approccio è tutt'altro che perfetto, perché, come ho capito dal codice, hai solo un blocco per l'intera applicazione. È meglio quando ciascuna entità di dati indipendente ha il proprio blocco. Quindi avresti una classe astratta come questa:

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

Quindi ereditare altre classi da questa classe astratta che implementa il blocco.

 constructor TAbstractData .Create; 
     begin 
     inherited Create; 
     InitializeCriticalSection(CriticalSection); 
     end; 

     procedure TAbstractData.Lock; 
     begin 
     EntercriticalSection(CriticalSection); 
     end; 

     procedure TAbstractData.Unlock; 
     begin 
     LeaveSection(CriticalSection); 
     end; 

     procedure TAbstractData.Destroy; 
     begin 
     DeleteCriticalSection(CriticalSection); 
     inherited Destroy; 
     end; 

A CriticalSection è il clas di sincronizzazione più efficiente, implementato in Windows finora. È praticamente gratuito: non consuma quasi risorse di sistema a meno che non vi sia conflitto di thread e non invoca costosi switch di contesto quando c'è solo un thread che utilizza i dati.

Dopo aver inviato la risposta, ho trovato un buon articolo su Internet - http://blog.synopse.info/post/2016/01/09/Safe-locks-for-multi-thread-applications - l'autore raccomanda un approccio simile.

Problemi correlati