1 / 65

Synchronisation

Synchronisation. Objectif du chapitre. Création d’une application ayant plusieurs threads Synchronisations entre threads Section critique Mutex Événement Sémaphore Exemples pratiques. Synchronisation.

veta
Download Presentation

Synchronisation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Synchronisation Synchronisation

  2. Objectif du chapitre • Création d’une application ayant plusieurs threads • Synchronisations entre threads • Section critique • Mutex • Événement • Sémaphore • Exemples pratiques Synchronisation

  3. Synchronisation • Nous avons vu comment créer un thread dans un processus dans le chapitre précédent. Nous poursuivons maintenant avec plusieurs threads dans un même processus. • Dans un premier exemple, “NOSYNC”, nous allons faire apparaître une difficulté lorsque plusieurs threads s’exécutent simultanément. • Dans les exemples suivants, nous travaillerons sur plusieurs solutions au problème. Synchronisation

  4. Création de 2 Threads • Créer un projet NOSYNC • Un process va créer 2 threads fils A et B • Ces threads font juste l’impression de messages • Début de thread • Texte • Fin de thread • La demande d’impression d’un texte fait que le thread perd la main Synchronisation

  5. NOSYNC main (1) #include "stdafx.h" DWORD WINAPI THREAD_A(LPVOID p); DWORD WINAPI THREAD_B(LPVOID p); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { HANDLE H1,H2; Synchronisation

  6. NOSYNC main (2) printf("debut du main NOSYNC\n"); H1=CreateThread(0, 0, THREAD_A, 0, 0, 0); H2=CreateThread(0, 0, THREAD_B, 0, 0, 0); Sleep(5000); CloseHandle(H1); CloseHandle(H2); printf("fin du main NOSYNC\n"); getchar(); return 0; } Synchronisation

  7. NOSYNC Thread_A DWORD WINAPI THREAD_A(LPVOID p) { printf("debut du thread A\n"); printf("le loup et "); printf("\nl'agneau "); printf("fin du thread A\n"); return 0; } Synchronisation

  8. NOSYNC Thread_B DWORD WINAPI THREAD_B(LPVOID p) { printf("debut du thread B\n"); printf("la cerise"); printf("sur le gateau\n"); printf("fin du thread B\n"); return 0; } Synchronisation

  9. Résultat de l’exécution Synchronisation

  10. Synchronisation • Les messages sont mélangés • Il faut « synchroniser » l’exécution des threads, c’est-à-dire, dans notre exemple, attendre qu’un message soit terminé avant d’imprimer l’autre • Synchronisation possible par • Section critique • Mutex • Événement (Event) • Sémaphore Synchronisation

  11. Section critique : types • Les types « section critique » et « pointeur sur section critique » sont définis par des typedef CRITICAL_SECTION cs; LPCRITICAL_SECTION lpcs; • Cela permet des contrôles par le compilateur et contribue à éviter un usage inapproprié Synchronisation

  12. Section critique : fonctions (1) • Initialisation d’une section critique void InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); • Entrée en section critique void EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); • Sortie d’une section critique void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); Synchronisation

  13. Section critique : fonctions (2) • Restitution des ressources void DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); • Variante d’entrée non bloquante BOOL TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); Synchronisation

  14. Section critique : application • Créer une application CRITIC qui imprime correctement les deux messages • Déclaration dans main ou en variable globale d’une variable section critique • Utilisation de cette variable dans thread_A et thread_B pour contrôler l’impression des messages Synchronisation

  15. CRITIC main (1) #include "stdafx.h" DWORD WINAPI THREAD_A(LPVOID p); DWORD WINAPI THREAD_B(LPVOID p); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { CRITICAL_SECTION cs; HANDLE H1,H2; Synchronisation

  16. CRITIC main (2) InitializeCriticalSection(&cs); printf("debut du main CRITIC\n"); H1=CreateThread( 0, 0, THREAD_A, &cs, 0, 0); H2=CreateThread( 0, 0, THREAD_B, &cs, 0, 0); Sleep(5000); CloseHandle(H1); CloseHandle(H2); DeleteCriticalSection(&cs); printf("fin du main CRITIC\n"); getchar(); return 0; } Synchronisation

  17. CRITIC thread_A DWORD WINAPI THREAD_A(LPVOID pCriticSec) { printf("debut du thread A\n"); EnterCriticalSection( (LPCRITICAL_SECTION)pCriticSec); printf("THREAD_A: le loup et "); printf("l'agneau\n"); LeaveCriticalSection( (LPCRITICAL_SECTION)pCriticSec); printf("fin du thread A\n"); return 0; } Synchronisation

  18. CRITIC thread_B DWORD WINAPI THREAD_B(LPVOID pCriticSec) { printf("debut du thread B\n"); EnterCriticalSection((LPCRITICAL_SECTION)p CriticSec); printf("THREAD_B: la cerise "); printf("sur le gateau\n"); LeaveCriticalSection((LPCRITICAL_SECTION)p CriticSec); printf("fin du thread B\n"); return 0; } Synchronisation

  19. Résultat de l’exécution Synchronisation

  20. Mutex • Mutex : raccourci pour mutual exclusion • Objet système destiné à gérer les synchronisations par exclusion mutuelle • Synchronisation • Intra-processus • Inter-processus • Alloué au plus à un thread à un instant donné Synchronisation

  21. Mutex : fonctions (1) • Création d’un Mutex HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName ); lpMutexAttributes : NULL pour CE bInitialOwner : prise ou non du mutex lpName : pointeur sur un nom ou NULL valeur retournée : création ou non du mutex, etc. Synchronisation

  22. MUTEX : fonctions (2) • Attente de disponibilité du mutex DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); hHandle : handle du mutex dwMilliseconds : INFINITE (pas de time-out) valeur de retour : état du mutex • Libération du mutex BOOL ReleaseMutex(HANDLE hMutex );valeur de retour : réussite ou non Synchronisation

  23. MUTEX : fonctions (2) • Attente de disponibilité du mutex DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); hHandle : handle du mutex dwMilliseconds : INFINITE (pas de time-out) valeur de retour : état du mutex • Libération du mutex BOOL ReleaseMutex(HANDLE hMutex );valeur de retour : réussite ou non Synchronisation

  24. Application MUTEX • Créer une application MUTEX • Utiliser les mutexes pour que les textes ne soient plus mélangés lors de l’impression Synchronisation

  25. MUTEX main (1) #include "stdafx.h" DWORD WINAPI THREAD_A(HANDLE hMutex); DWORD WINAPI THREAD_B(HANDLE hMutex); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { HANDLE hMutex,H1,H2; printf("debut du main MUTEX\n"); hMutex=CreateMutex(NULL,FALSE,NULL); Synchronisation

  26. MUTEX main (2) H1=CreateThread(0,0,THREAD_A,hMutex,0,0); H2=CreateThread(0,0,THREAD_B,(LPVOID)hMutex,0,0); Sleep(5000); CloseHandle(H1); CloseHandle(H2); CloseHandle(hMutex); printf("fin du main MUTEX\n"); getchar(); return 0; } Synchronisation

  27. MUTEX thread_A DWORD WINAPI THREAD_A(HANDLE hMut) { printf("debut du thread A\n"); WaitForSingleObject(hMut,INFINITE); printf("THREAD_A: le loup et "); printf("l'agneau\n"); ReleaseMutex(hMut); printf("fin du thread A\n"); return 0; } Synchronisation

  28. MUTEX Thread_B DWORD WINAPI THREAD_B(HANDLE hMut) { printf("debut du thread B\n"); WaitForSingleObject(hMut,INFINITE); printf("THREAD_B: la cerise "); printf("sur le gateau\n"); ReleaseMutex(hMut); printf("fin du thread B\n"); return 0; } Synchronisation

  29. Résultat de l’exécution Synchronisation

  30. Synchronisation par événement • Autre forme de synchronisation plus souple que par les mutex • Gestion plus riche des événements • Création • Prise de possession • Restitution • Transmission de données • Ouvertures multiples Synchronisation

  31. Événements : fonctions (1) • Création d’un événementHANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPTSTR lpName ); lpEventAttributes: NULL pour CE bManualReset: TRUE autorise ResetEvent bInitialState: TRUE événement disponible lpName: NULL pour un événement sans nom Synchronisation

  32. Événements : fonctions (2) • Ouverture d’événementHANDLE OpenEvent(DWORD dwDesiredAcess, BOOL bInheritHandle, LPCTSTR lpName); • Fournit un handle sur un événement déjà créé par CreateEvent • Correspondance par le nom lpName Synchronisation

  33. Événements : fonctions (3) • Attente d’événementDWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); • Activation de l’événement BOOL SetEvent(HANDLE hEvent); • Désactivation de l’événement BOOL ResetEvent(HANDLE hEvent); Synchronisation

  34. Événements : fonctions (4) • Dépôt d’une donnéeBOOL SetEventData(HANDLE hEvent, DWORD dwData);hEvent : handle de l’événementdwData : donnée à affecter • Récupération de la donnée déposée DWORD GetEventData(HANDLE hEvent); valeur de retour : la donnée déposée Synchronisation

  35. Application EVENT • Créer une application EVENT • EventA est créé actif dans le thread A pour autoriser la tâche A à démarrer • EventB est créé inactif dans le thread B • La tâche A désactivera EventA en début de tâche et activera EventB en fin de tâche • La tâche B désactivera EventB en début de tâche et réactivera EventA en fin de tâche • Les 2 tâches vont s’activer mutuellement Synchronisation

  36. EVENT main (1) #include "stdafx.h" DWORD WINAPI THREAD_A(LPVOID p); DWORD WINAPI THREAD_B(LPVOID p); HANDLE hEventA,hEventB; //variables globales pour… int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { HANDLE H1,H2; printf("debut du main EVENT\n"); Synchronisation

  37. EVENT main (2) hEventA=CreateEvent(NULL,TRUE,TRUE,NULL); hEventB=CreateEvent(NULL,TRUE,FALSE,NULL); H1=CreateThread(0,0,THREAD_A,0,0,0); H2=CreateThread(0,0,THREAD_B,0,0,0); Sleep(5000); CloseHandle(H1); CloseHandle(H2); CloseHandle(hEventA); CloseHandle(hEventB); printf("fin du main EVENT\n"); getchar(); return 0; } Synchronisation

  38. EVENT THREAD_A DWORD WINAPI THREAD_A(LPVOID p) { printf("debut du thread A\n"); WaitForSingleObject(hEventA,INFINITE); printf("THREAD_A: le loup et "); printf("l'agneau\n"); ResetEvent(hEventA); SetEvent(hEventB); printf("fin thread A\n"); return 0; } Synchronisation

  39. EVENT THREAD_B DWORD WINAPI THREAD_B(LPVOID p) { printf("debut thread B\n"); WaitForSingleObject(hEventB,INFINITE); printf("THREAD_B: la cerise "); printf("sur le gateau\n"); ResetEvent(hEventB); SetEvent(hEventA); printf("fin thread B\n"); return 0; } Synchronisation

  40. Résultat de l’exécution Synchronisation

  41. Application EVENT_NOM • L’application est du même style que EVENT, mais montre l’usage d’autres fonctionnalités : • Événements nommés • Passage de donnée • Utilisation d’un dépassement de délai • Le thread imprime un message ou un autre suivant la donnée fournie, 1 ou 2 Synchronisation

  42. EVENT_NOM : main (1) // EVENT_NOM.cpp : Defines the entry point for the… #include "stdafx.h" #include "Pkfuncs.h"//pour les fonctions SetEventData… DWORD WINAPI THREAD_A(LPVOID p); DWORD WINAPI THREAD_B(LPVOID p); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) Synchronisation

  43. EVENT_NOM : main (2) { HANDLE H1,H2; HANDLE hEventA,hEventB; LPTSTR pNomEventA={L"NOM_EVENT_A"}; LPTSTR pNomEventB={L"NOM_EVENT_B"}; printf("debut du main EVENT_NOM\n"); hEventA=CreateEvent(NULL,TRUE,TRUE,pNomEventA); SetEventData(hEventA,1); hEventB=CreateEvent(NULL,TRUE,FALSE,pNomEventB); H1=CreateThread(0,0,THREAD_A,0,0,0); H2=CreateThread(0,0,THREAD_B,0,0,0); Synchronisation

  44. EVENT_NOM : main (3) Sleep(5000); CloseHandle(H1); CloseHandle(H2); CloseHandle(hEventA); CloseHandle(hEventB); printf("fin du main EVENT_NOM\n"); getchar(); return 0; } Synchronisation

  45. EVENT_NOM : THREAD_A (1) DWORD WINAPI THREAD_A(LPVOID p) { DWORD dwData_A; DWORD dwTime_out=1000; HANDLE hEvent_A,hEvent_B; LPTSTR pNomEventA={L"NOM_EVENT_A"}; LPTSTR pNomEventB={L"NOM_EVENT_B"}; printf("debut du thread A\n"); hEvent_A=OpenEvent(EVENT_ALL_ACCESS,FALSE,pNomEventA); hEvent_B=OpenEvent(EVENT_ALL_ACCESS,FALSE,pNomEventB); Synchronisation

  46. EVENT_NOM : THREAD_A (2) while(WAIT_OBJECT_0==WaitForSingleObject(hEvent_A,dwTime_out)) { dwData_A=GetEventData(hEvent_A); printf("THREAD_A: fable %d : ",dwData_A); switch (dwData_A) { case 1 : printf("le loup "); printf("et l'agneau\n"); break; case 2 : printf("le lion et "); printf("le rat\n"); break; default : break; } Synchronisation

  47. EVENT_NOM : THREAD_A (3) ResetEvent(hEvent_A); SetEvent(hEvent_B); } printf("fin thread A\n"); return 0; Synchronisation

  48. EVENT_NOM : THREAD_B (1) DWORD WINAPI THREAD_B(LPVOID p) { HANDLE hEvent_A,hEvent_B; LPTSTR pNomEventA={L"NOM_EVENT_A"}; LPTSTR pNomEventB={L"NOM_EVENT_B"}; printf("debut thread B\n"); hEvent_A=OpenEvent(EVENT_ALL_ACCESS,FALSE,pNomEventA); SetEventData(hEvent_A,2); hEvent_B=OpenEvent(EVENT_ALL_ACCESS,FALSE,pNomEventB); WaitForSingleObject(hEvent_B,INFINITE); Synchronisation

  49. EVENT_NOM : THREAD_B (2) printf("THREAD_B: la cerise "); printf("sur le gateau\n"); ResetEvent(hEvent_B); SetEvent(hEvent_A); Sleep(2000); //suivant valeur : fin de A avant B ou de B avant A printf("fin thread B\n"); return 0; } Synchronisation

  50. Résultat de l’exécution Synchronisation

More Related