In questi giorni ho avuto una pacifica(!?!?) discussione in privato sull'uso dei lock. Il Framework mette a disposizione varie classi per questa importante necessità. La più semplice è con l'uso del SyncLock di Visual Basic.Net (Lock {} in C#) o con la classe Monitor presente in System.Threading. Per vedere le differenze scriviamo due classi, la prima che utilizza il SyncLock di VB, la seconda direttamente la classe Monitor:
public class WithLock public Conteggio as integer=0 public sub Aumenta() SyncLock me conteggio+=1 end synclock end sub end class<p />public class WithNoLock public Conteggio as integer=0 public sub Aumenta() Monitor.Enter(me) conteggio+=1 Monitor.Exit(me) end sub end class
Ora a apriamo il Reflecton per vedere nella compilazione che cosa ha creato il Framework:
Puvlic class WithLock
Public Sub Aumenta() Dim lock1 As WithLock = Me Monitor.Enter(lock1) Try Me.Conteggio = (Me.Conteggio + 1) Return Finally Monitor.Exit(lock1) End Try End Sub End Class
Public Class WithNoLock
Public Sub Aumenta() Monitor.Enter(Me) Me.Conteggio = (Me.Conteggio + 1) Monitor.Exit(Me) End Sub End Class
Come si può vedere il Framework ha modificato la funzione del Visual Basic SyncLock nell'equivalente Monitor.Enter... Non c'è alcuna differenza dunque... be', una evidente c'è: nel caso dell'utilizzo della funzione SyncLock il framework ci garanrisce che il lock venga tolto alla fine del'elaborazione della funzione anche in presenza di errori nel blocco del codice all'interno del lock. Infatti, con l'utilizzo della classe Monitor si deve sempre essere certi di sbloccare il lock creato con l'Enter, altrimenti quella risorsa rimarrà bloccata in eterno, e il modo utilizzato dal Framework - l'inserimento della linea "Monitor.Exit()" nel blocco Finally ci garantisce questo.
Dunque sembra che il modo migliore sia l'utilizzo degli appositi comandi SyncLock e Lock {} di Visual Basic e C#. Ma è realmente così?
Nei casi reali, quante volte viene lasciato un blocco di codice importante - in cui si desidera utilizzare addirittura il lock delle risorse - senza una gestione personale degli errori? Rivediamo il codice d'esempio modificandolo con qualcosa di reale:
public class WithLock2 public Conteggio as integer=0 public sub Aumenta() try SyncLock me conteggio+=1 end synclock catch ' .... end try end sub end class<p />public class WithNoLock2 public Conteggio as integer=0 public sub Aumenta() try Monitor.Enter(me) conteggio+=1 catch ' .... finally Monitor.Exit(me) end try end sub end class
Vediamo ora il codice prodotto dal Framework:
Public Class WithLock2 Public Sub Aumenta() Dim lock1 As WithLock2 Try lock1 = Me Monitor.Enter(lock1) Try Me.Conteggio = (Me.Conteggio + 1) Return Finally Monitor.Exit(lock1) End Try Return Catch Exception exception1 ProjectData.SetProjectError(exception1) ProjectData.ClearProjectError Return End Try End Sub End Class
Addiriturra sono presenti due blocchi try... mentre nella versione il con Monitor nativo:
Public Class WithNoLock2 Public Sub Aumenta() Try Monitor.Enter(Me) Me.Conteggio = (Me.Conteggio + 1) Return Catch Exception exception1 ProjectData.SetProjectError(exception1) ProjectData.ClearProjectError Return Finally Monitor.Exit(Me) End Try End Sub End Class
E' restata immutata, più veloce e più leggibile. Quali sono dunque le conclusioni di questo blog? Boh! Chi aveva ragione? Mah... :)
Uffa... non c'è neanche la tappa del giro d'Italia oggi...
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- C# e Net 6 in Kubernetes con Prometheus e Grafana, il 12 gennaio 2022 alle 21:58
- Snaturare Kubernetes evitando i custom container Docker, il 6 gennaio 2022 alle 19:40
- Provando Kaniko in Kubernetes come alternativa a Docker per la creazione di immagini, il 18 dicembre 2021 alle 20:11
- Divertissement con l'OpenID e Access Token, il 6 dicembre 2021 alle 20:05
- Operator per Kubernetes in C# e Net Core 6., il 28 novembre 2021 alle 19:44
- RBAC in Kubernetes verso gli operator, il 21 novembre 2021 alle 20:52