Utilizzare il lock di oggetti con il .NET Framework

di Andrea Zani, in UserScript, ASP.NET, VB.NET,

In applicazioni multiutente come le nostre web application è indispensabile poter eseguire dei "blocchi" delle risorse in modo che l'accesso simultaneo da parte di più utenti non corrompa o modifichi il contenuto dello stesso.

Prendiamo ad esempio un banale contatore di accessi che memorizza i dati in un file di testo. Esso si baserà su queste operazioni:

1) lettura file contenente i dati
2) modifica del dato
3) aggiornamento del dato nel file

E' facile immaginare il caso in cui due utenti accedono contemporaneamente. Se l'utente B inizia il passo uno quando l'utente A, per esempio, è al punto due, esso troverà ancora il dato iniziale, mentre l'utente A memorizzerà il nuovo dato che sarà riscritto dall'utente B alla fine delle operazioni.

Per evitare questo problema - ed altri simili che potrebbero nascere con l'aumento di pagine erogate dal nostro server, come malfunzionamenti e altri di difficile soluzione - possiamo utilizzare il lock delle risorse. Abbiamo già visto nelle Classic ASP l'utilizzo del Lock abbinato all'oggetto Application (script #14). Con ASP.NET abbiamo a disposione blocchi "granulari" che ci permettono il blocco solo della risorsa interessata.

Le istruzioni per eseguire questo sono per C#:

lock (oggetto)
{
...
}

e per VB.NET:

SyncLock (oggetto)
...
end SyncLock

Come "oggetto" possiamo specificare "this" per il C# o "Me" per il VisualBasic, in tal caso il lock sarà basato sull'intera classe, anche se questo non è consigliato.

Vediamo come ricostruire l'esempio dell'aggiornamento di un file con questi comandi:

Funzione Aggiornamento
1) SyncLock (me)
2) lettura file contenente i dati
3) modifica del dato
4) aggiornamento del dato nel file
5) end SyncLock

In questo modo quando più utenti richiameranno questo codice, saranno accodati finché la richiesta in elaborazione non sarà terminata.

Come detto prima, il lock sull'intera classe non è consigliato visto che potrebbe essere necessario bloccare altre risorse, e in tal caso il lock bloccherebbe anche l'esecuzione di codice del tutto estraneo per quella necessità.

Una delle tecniche consigliate in questo ambito è l'utilizzo di oggetti fittizzi per il lock. Se nell'esempio precedente avessimo due contatori basati su due file di testo aggiornati da due funzioni, scriveremo:

private shared BloccoFile1 as new Object()
private shared BloccoFile2 as new Object()

Function AggiornamentoFile1()
  SyncLock (BloccoFile1)
  ' 1) lettura file contenente i dati
  ' 2) modifica del dato
  ' 3) aggiornamento del dato nel file
  end SyncLock
End Function

Function AggiornamentoFile2
  SyncLock (BloccoFile2)
  ' 1) lettura file contenente i dati
  ' 2) modifica del dato
  ' 3) aggiornamento del dato nel file
  end SyncLock
End Function

L'ideale, comunque, rimane l'utilizzo di classi diverse per le risorse su cui effettuare il lock.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi