Synchronisation des Processus et Threads
Introduction
Quand plusieurs threads ou processus accedent a des ressources partagees, il faut coordonner leurs acces pour eviter les problemes de concurrence.
Problemes de Concurrence
Race Condition (Condition de course)
Quand le resultat depend de l'ordre d'execution non determine.
Thread 1 Thread 2
-------- --------
Lire compteur (= 5)
Lire compteur (= 5)
Incrementer (= 6)
Incrementer (= 6)
Ecrire (= 6)
Ecrire (= 6)
Resultat: 6 au lieu de 7!
Section Critique
Zone de code qui accede a une ressource partagee et doit etre executee par un seul thread a la fois.
Deadlock (Interblocage)
Situation ou deux threads s'attendent mutuellement indefiniment.
Thread 1: Detient A, attend B
Thread 2: Detient B, attend A
-> Blocage permanent!
Mecanismes de Synchronisation Windows
Vue d'ensemble
| Mecanisme | Portee | Utilisation |
|---|---|---|
| Critical Section | Intra-processus | Acces rapide, meme processus |
| Mutex | Inter-processus | Exclusion mutuelle, nomme |
| Semaphore | Inter-processus | Controle d'acces multiple |
| Event | Inter-processus | Signalisation |
| Interlocked | Intra-processus | Operations atomiques simples |
Critical Section
Concept
Mecanisme leger pour synchroniser des threads au sein d'un meme processus.
Caracteristiques
- Plus rapide que Mutex
- Limite a un seul processus
- Non nomme
Utilisation (C/C++)
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
// Section critique - un seul thread a la fois
compteur++;
LeaveCriticalSection(&cs);
DeleteCriticalSection(&cs);
En PowerShell (simulation)
# Utilisation de [System.Threading.Monitor]
$lockObj = New-Object Object
$compteur = 0
[System.Threading.Monitor]::Enter($lockObj)
try {
# Section critique
$compteur++
}
finally {
[System.Threading.Monitor]::Exit($lockObj)
}
Mutex (Mutual Exclusion)
Concept
Objet de synchronisation permettant l'exclusion mutuelle entre processus.
Caracteristiques
- Peut etre nomme (accessible entre processus)
- Plus lent que Critical Section
- Detection de deadlock possible
Utilisation en PowerShell
# Creer ou ouvrir un mutex nomme
$mutexName = "Global\MonMutex"
$mutex = New-Object System.Threading.Mutex($false, $mutexName)
try {
# Attendre le mutex (timeout 5 secondes)
if ($mutex.WaitOne(5000)) {
try {
Write-Host "Mutex acquis - section critique"
# Travail exclusif ici
Start-Sleep -Seconds 2
}
finally {
$mutex.ReleaseMutex()
Write-Host "Mutex libere"
}
}
else {
Write-Host "Timeout - mutex non acquis"
}
}
finally {
$mutex.Close()
}
Mutex nomme vs anonyme
| Type | Nom | Portee |
|---|---|---|
| Anonyme | Aucun | Threads du meme processus |
| Local | "Local\Nom" | Session utilisateur |
| Global | "Global\Nom" | Tous les processus systeme |
Semaphore
Concept
Permet de limiter le nombre d'acces simultanees a une ressource.
Difference avec Mutex
| Mutex | Semaphore |
|---|---|
| 1 seul acces | N acces simultanees |
| Proprietaire unique | Pas de proprietaire |
Utilisation en PowerShell
# Semaphore avec 3 places
$semName = "Global\MonSemaphore"
$semaphore = New-Object System.Threading.Semaphore(3, 3, $semName)
try {
if ($semaphore.WaitOne(5000)) {
try {
Write-Host "Place acquise dans le semaphore"
# Travail limite a 3 threads simultanees
Start-Sleep -Seconds 2
}
finally {
$semaphore.Release()
Write-Host "Place liberee"
}
}
}
finally {
$semaphore.Close()
}
Cas d'usage
- Pool de connexions base de donnees
- Limitation de telechargements simultanees
- Controle de ressources limitees
Event
Concept
Permet a un thread de signaler un evenement a d'autres threads.
Types d'events
| Type | Comportement |
|---|---|
| AutoReset | Libere un seul thread puis se remet a non-signale |
| ManualReset | Reste signale jusqu'a reset explicite |
Utilisation en PowerShell
# Event ManualReset
$eventName = "Global\MonEvent"
$event = New-Object System.Threading.EventWaitHandle(
$false, # Initial state: non signale
[System.Threading.EventResetMode]::ManualReset,
$eventName
)
# Dans le thread producteur
$event.Set() # Signaler
$event.Reset() # Remettre a non signale
# Dans le thread consommateur
if ($event.WaitOne(5000)) {
Write-Host "Event recu!"
}
$event.Close()
Interlocked Operations
Concept
Operations atomiques sur des variables, sans besoin de lock explicite.
Operations disponibles
| Operation | Description |
|---|---|
| Increment | Incremente de 1 |
| Decrement | Decremente de 1 |
| Add | Ajoute une valeur |
| Exchange | Echange des valeurs |
| CompareExchange | Echange conditionnel |
Utilisation en PowerShell
# Increment atomique
$compteur = 0
[System.Threading.Interlocked]::Increment([ref]$compteur)
Write-Host "Compteur: $compteur"
# Add atomique
[System.Threading.Interlocked]::Add([ref]$compteur, 10)
Write-Host "Compteur apres add: $compteur"
# Exchange atomique
$oldValue = [System.Threading.Interlocked]::Exchange([ref]$compteur, 100)
Write-Host "Ancienne valeur: $oldValue, Nouvelle: $compteur"
Bonnes Pratiques
Eviter les Deadlocks
- Ordre constant: Toujours acquerir les locks dans le meme ordre
- Timeouts: Utiliser des timeouts pour detecter les blocages
- Minimiser: Garder les sections critiques courtes
Exemple de deadlock evite
# MAUVAIS - risque de deadlock
# Thread 1: Lock A puis Lock B
# Thread 2: Lock B puis Lock A
# BON - ordre constant
# Thread 1: Lock A puis Lock B
# Thread 2: Lock A puis Lock B (meme ordre!)
Performance
| Mecanisme | Performance | Cas d'usage |
|---|---|---|
| Interlocked | Tres rapide | Operations simples |
| Critical Section | Rapide | Meme processus |
| Mutex | Moyen | Inter-processus |
| Semaphore | Moyen | Acces multiple limite |
Detection des Problemes
Process Explorer
- View > Show Lower Pane
- Handle view: voir les handles de synchronisation
WinDbg
!locks # Afficher les locks
!handle # Afficher les handles
!analyze -hang # Analyser un hang/deadlock
Performance Monitor
Compteurs utiles:
Process > Handle CountThread > Context Switches/sec
Exercices
- Creez un script avec deux jobs PowerShell qui utilisent un mutex partage
- Implementez un compteur thread-safe avec Interlocked
- Creez un semaphore qui limite a 2 executions simultanees