انتقل إلى المحتوى الرئيسي

تزامن العمليات والخيوط

مقدمة​

عندما تصل عدة خيوط أو عمليات إلى موارد مشتركة، يجب تنسيق وصولها لتجنب مشاكل التنافس.

مشاكل التنافس​

Race Condition (شرط السباق)​

عندما يعتمد النتيجة على ترتيب تنفيذ غير محدد.

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​

منطقة من الكود تصل إلى مورد مشترك ويجب تنفيذها بواسطة خيط واحد فقط في كل مرة.

Deadlock (توقف)​

حالة حيث ينتظر خيطان بعضهما البعض إلى ما لا نهاية.

Thread 1: Detient A, attend B
Thread 2: Detient B, attend A
-> Blocage permanent!

آليات التزامن في Windows​

نظرة عامة​

MecanismePorteeUtilisation
Critical SectionIntra-processusوصول سريع، نفس العملية
MutexInter-processusاستبعاد متبادل، مسمى
SemaphoreInter-processusالتحكم في الوصول المتعدد
EventInter-processusالإشارة
InterlockedIntra-processusعمليات ذرية بسيطة

Critical Section​

المفهوم​

آلية خفيفة لتزامن الخيوط داخل نفس العملية.

الخصائص​

  • أسرع من Mutex
  • محدود بعملية واحدة
  • غير مسمى

الاستخدام (C/C++)​

CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);

EnterCriticalSection(&cs);
// Section critique - un seul thread a la fois
compteur++;
LeaveCriticalSection(&cs);

DeleteCriticalSection(&cs);

في PowerShell (محاكاة)​

# 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 (الاستبعاد المتبادل)​

المفهوم​

كائن تزامن يسمح بالاستبعاد المتبادل بين العمليات.

الخصائص​

  • يمكن أن يكون مسمى (متاح بين العمليات)
  • أبطأ من Critical Section
  • إمكانية اكتشاف التوقف

الاستخدام في 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 مسمى مقابل غير مسمى​

TypeNomPortee
AnonymeAucunThreads du meme processus
Local"Local\Nom"Session utilisateur
Global"Global\Nom"Tous les processus systeme

Semaphore​

المفهوم​

يسمح بتحديد عدد الوصولات المتزامنة إلى مورد.

الفرق مع Mutex​

MutexSemaphore
1 seul accesN acces simultanees
Proprietaire uniquePas de proprietaire

الاستخدام في 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()
}

حالات الاستخدام​

  • مجموعة اتصالات قاعدة البيانات
  • تحديد التنزيلات المتزامنة
  • التحكم في الموارد المحدودة

Event​

المفهوم​

يسمح لخيط بالإشارة إلى حدث لخيوط أخرى.

أنواع الأحداث​

TypeComportement
AutoResetLibere un seul thread puis se remet a non-signale
ManualResetReste signale jusqu'a reset explicite

الاستخدام في 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​

المفهوم​

عمليات ذرية على المتغيرات، دون الحاجة إلى قفل صريح.

العمليات المتاحة​

OperationDescription
IncrementIncremente de 1
DecrementDecremente de 1
AddAjoute une valeur
ExchangeEchange des valeurs
CompareExchangeEchange conditionnel

الاستخدام في 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"

الممارسات الجيدة​

تجنب التوقفات​

  1. ترتيب ثابت: احصل دائمًا على الأقفال بنفس الترتيب
  2. Timeouts: استخدم timeouts لاكتشاف التوقفات
  3. التقليل: حافظ على الأقسام الحرجة قصيرة

مثال على تجنب التوقف​

# 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!)

الأداء​

MecanismePerformanceCas d'usage
InterlockedTres rapideOperations simples
Critical SectionRapideMeme processus
MutexMoyenInter-processus
SemaphoreMoyenAcces multiple limite

اكتشاف المشاكل​

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​

المؤشرات المفيدة:

  • Process > Handle Count
  • Thread > Context Switches/sec

التمارين​

  1. قم بإنشاء سكربت مع وظيفتين PowerShell تستخدمان mutex مشترك
  2. قم بتنفيذ عداد آمن للخيوط باستخدام Interlocked
  3. قم بإنشاء semaphore يقتصر على تنفيذين متزامنين

المراجع​