La sincronizzazione dell'accesso alle risorse in ambiente multi-thread viene gestito tramite interfaccia ISync, composta da tre metodi:
- Acquire: ottiene il lock sulla risorsa desiderata.
- Release: rilascia il lock precedentemente acquisito.
- Attempt: ottiene il lock sulla risorsa desidera per un tempo massimo espresso in millisecondi, al termine del quale viene automaticamente rilasciato il lock.
Spring.NET offre due implementazione della suddetta interfaccia:
- Latch: rappresenta una condizione booleana. Questa classe viene tipicamente utilizzata per "dare" il segnale di partenza ad un gruppo di thread.
- Semaphore: rappresenta l'implementazione di un semaforo. Questa classe viene tipicamente utilizzata per limitare il numero di thread che accedono ad una risorsa.
Come sempre un esempio vale più di mille parole. Cominciamo con la creazione di una Console Application e di una classe di nome Worker, la quale accetta in ingresso due istanze di ISync. Questa classe avrà un banale metodo che inizialmente aquisisce un lock di un Latch ed alla fine rilascia un lock di un Semaphore:
1: public class Worker
2: {
3: public bool worked;
4: ISync startPermit;
5: ISync workedSync;
6:
7: public Worker(ISync startPermit, ISync workedSync)
8: {
9: this.startPermit = startPermit;
10: this.workedSync = workedSync;
11: }
12:
13: public void DoWork()
14: {
15: Console.WriteLine(String.Format("Thread {0} inizialized", System.Threading.Thread.CurrentThread.ManagedThreadId));
16: startPermit.Acquire();
17: //accedo alle risorse necessarie
18: Console.WriteLine(String.Format("Thread {0} work in progress...", System.Threading.Thread.CurrentThread.ManagedThreadId));
19: worked = true;
20: Console.WriteLine(String.Format("Thread {0} finished", System.Threading.Thread.CurrentThread.ManagedThreadId));
21: workedSync.Release();
22: }
23: }
adesso nel Main inseriamo il seguente codice:
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: int n = 10;
6:
7: Latch startPermit = new Latch();
8: Semaphore wait = new Semaphore(-(n - 1));
9:
10: Worker[] workers = new Worker[n];
11:
12: Console.WriteLine("Inizialize all Thread...");
13: for (int i = 0; i < n; ++i)
14: {
15: workers[i] = new Worker(startPermit, wait);
16: new System.Threading.Thread(new System.Threading.ThreadStart(workers[i].DoWork)).Start();
17: }
18:
19: Console.WriteLine("Start work!");
20: startPermit.Release();
21:
22: wait.Acquire();
23: Console.WriteLine("Work complited.");
24:
25: Console.Read();
26: }
27: }
la logica è molto semplice, istanzio entrambe le implementazioni di ISync, creo e lancio una serie di thread che puntano al metodo DoWork, appena quest'ultimi sono tutti inizializzati rilascio il Latch in modo da segnalare l'inizio dei "lavori" ed in fine grazie al Semaphore attendo la fine di tutti i thread.
Technorati Tags:
Spring.NET