You can learn from examples for better understanding.
# Include <windows. h>
# Include <iostream. h>
// Statement of two threads
Dword winapi Fun1Proc (LPVOID lpParameter );
Dword winapi Fun2Proc (LPVOID lpParameter );
Int tickets = 100;
CRITICAL_SECTION g_cs; // defines a critical section.
Int main ()
{
HANDLE hThread1;
HANDLE hThread2;
HThread1 = CreateThread (NULL, 0, Fun1Proc, NULL, 0, NULL );
HThread2 = CreateThread (NULL, 0, Fun2Proc, NULL, 0, NULL );
CloseHandle (hThread1 );
CloseHandle (hThread2 );
InitializeCriticalSection (& g_cs); // initialize the critical section
Sleep (4000 );
DeleteCriticalSection (& g_cs); // when there is no resource in the critical section, release the critical section (Can you say this )???
Return 0;
}
Dword winapi Fun1Proc (LPVOID lpParameter)
{
While (TRUE)
{
EnterCriticalSection (& g_cs); // This thread enters the critical section
If (tickets> 0)
{
Sleep (1 );
Cout <"Thread1 effectickets:" <tickets -- <endl;
}
Else
{
Break;
}
LeaveCriticalSection (& g_cs); // exit the critical section
}
Return0;
}
Dword winapi Fun2Proc (LPVOID lpParameter)
{
While (TRUE)
{
EnterCriticalSection (& g_cs); // This thread enters the critical section
If (tickets> 0)
{
Sleep (1 );
Cout <"Thread2 extends tickets:" <tickets -- <endl;
}
Else
{
Break;
}
LeaveCriticalSection (& g_cs); // exit the critical section
}
Return 0;
}
Note:
1Key code segments (critical sections) work in user mode
2. A critical code segment refers to a small code segment before the code is executed. It must exclusively access certain resources.
3. The key code segment is to work as a user. The synchronization speed is fast, but it is easy to enter the deadlock status when using key code segments. The timeout value cannot be set while waiting for the key code segment to enter.
4. Thread deadlock thread 1 has the critical section object. Wait for the ownership of object B in the critical section. Thread 2 has object B in the critical section and waits for the ownership of object A in the critical section, resulting in A deadlock.
5. They cannot be used to synchronize various threads in multiple processes.
The following example shows a deadlock.
# Include <windows. h>
# Include <iostream. h>
// 1. Two thread declarations
Dword winapi Fun1Proc (LPVOID lpParameter );
Dword winapi Fun2Proc (LPVOID lpParameter );
Int tickets = 100;
CRITICAL_SECTION g_csA; // 2. Define two critical zones
CRITICAL_SECTION g_csB;
Int main ()
{
HANDLE hThread1;
HANDLE hThread2;
HThread1 = CreateThread (NULL, 0, Fun1Proc, NULL, 0, NULL );
HThread2 = CreateThread (NULL, 0, Fun2Proc, NULL, 0, NULL );
CloseHandle (hThread1 );
CloseHandle (hThread2 );
InitializeCriticalSection (& g_csA); // 3. initialize the critical section
InitializeCriticalSection (& g_csB );
Sleep (4000 );
DeleteCriticalSection (& g_csA); // 4. Release the critical section if there are no resources in the critical section.
DeleteCriticalSection (& g_csB );
Return 0;
}
Dword winapi Fun1Proc (LPVOID lpParameter)
{
// 11. Two critical zones and two threads will crash. The thread cannot enter the critical section g_csB while waiting. The thread cannot enter the critical section g_csA while waiting
While (TRUE)
{
EnterCriticalSection (& g_csA); // 5. The thread enters the critical section g_csA.
Sleep (1); // 6. The thread enters the Sleep state. The thread starts when the time segment ends.
EnterCriticalSection (& g_csB); // 9. The thread enters the critical section g_csB, but the critical section g_csB is occupied by the thread. Therefore, you can only wait for the time segment to be handed over to the thread.
If (tickets> 0)
{
Sleep (1 );
Cout <"thread1 effectickets:" <tickets -- <Endl;
}
Else
{
Break;
}
Leavecriticalsection (& g_csb); // exit the critical section
Leavecriticalsection (& g_csa );
}
Return 0;
}
DWORD winapi fun2proc (lpvoid lpparameter)
{
While (true)
{
Entercriticalsection (& g_csb); // 7. The thread enters the critical section g_csb.
Sleep (1); // 8. The thread enters the sleep state. The thread starts when the time segment ends.
EnterCriticalSection (& g_csA); // 10. The thread enters the critical section g_csA, but the critical section g_csA is occupied by the thread. Therefore, you can only wait for the time segment to be handed over to the thread.
If (tickets> 0)
{
Sleep (1 );
Cout <"Thread2 extends tickets:" <tickets -- <endl;
}
Else
{
Break;
}
LeaveCriticalSection (& g_csA );
LeaveCriticalSection (& g_csB); // exit the critical section
}
Return 0;
}