Before reading this article, we recommend reading the following sister articles:
"Second-kill multithreaded fourth" a classic multi-threaded synchronization problem
"Second-kill multithreaded fifth" Classic thread synchronization key section CS
"Second-kill multithreaded sixth" Classic thread synchronization events event
"Second-kill multithreaded seventh" classic thread synchronization mutex mutex
The use of Critical segment CS, event events, mutex mutex in classic thread synchronization problems is described earlier. This article introduces the use of semaphore semaphore to solve this problem.
First also to see how to use the semaphore, Semaphore semaphore commonly have three functions, easy to use. Here are the prototypes and instructions for using these functions.
The first of the CreateSemaphore
function function: Create semaphore
Function Prototypes:
HANDLE CreateSemaphore (
Lpsecurity_attributes Lpsemaphoreattributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpname
);
Function Description:
The first parameter represents the security control, which is typically passed directly to null.
The second parameter represents the initial resource quantity.
The third parameter represents the maximum number of concurrent quantities.
The fourth parameter represents the name of the semaphore, and passing in NULL indicates the amount of anonymous semaphore.
A second OpenSemaphore
function function: Turn on semaphore
Function Prototypes:
HANDLE OpenSemaphore (
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpname
);
Function Description:
The first parameter represents access rights to the generic incoming semaphore_all_access. Detailed explanations can be viewed in the MSDN documentation.
The second parameter represents the semaphore handle inheritance, which is generally passed to true.
The third parameter represents a name, and each thread in a different process can make sure that they access the same semaphore by name.
A third ReleaseSemaphore
function function: The current resource count for incrementing semaphores
Function Prototypes:
BOOL ReleaseSemaphore (
HANDLE Hsemaphore,
LONG lReleaseCount,
Lplong Lppreviouscount
);
Function Description:
The first parameter is the handle to the semaphore.
The second parameter indicates the number of increments, which must be greater than 0 and not exceed the maximum number of resources.
The third parameter can be used to pass out the previous resource count, and set to NULL to indicate that no outgoing is required.
Note: the current number of resources is greater than 0, indicating that the semaphore is triggered, equals 0 indicates that the resource has been exhausted so the semaphore is triggered at the end. when the wait function is called on the semaphore, the wait function checks the current resource count of the semaphore if it is greater than 0 (that is, the semaphore is in the trigger state), minus 1, and returns the calling thread to continue execution. A thread can call the wait function multiple times to reduce the semaphore.
Cleanup and destruction of the last signal volume
Because the semaphore is a kernel object, you can use CloseHandle () to complete the cleanup and destruction.
Set a semaphore and a key segment in the classic multithreaded problem. The synchronization of the main thread and the sub-thread is handled by the semaphore, and the mutual exclusion between the sub-threads is handled by the critical section. See the code:
[CPP]View PlainCopy
- #include <stdio.h>
- #include <process.h>
- #include <windows.h>
- Long G_nnum;
- unsigned int __stdcall fun (void *ppm);
- const int thread_num = 10;
- Signal volume and critical segment
- HANDLE G_hthreadparameter;
- Critical_section G_csthreadcode;
- int main ()
- {
- printf ("Classic thread sync semaphore semaphore\n");
- printf ("-by Morewindows (http://blog.csdn.net/MoreWindows)--\n\n");
- //Initialize semaphores and critical segments
- G_hthreadparameter = CreateSemaphore (null, 0, 1, NULL); //Current 0 resources, maximum allowed 1 simultaneous access
- InitializeCriticalSection (&g_csthreadcode);
- HANDLE Handle[thread_num];
- G_nnum = 0;
- int i = 0;
- While (i < thread_num)
- {
- Handle[i] = (handle) _beginthreadex (NULL, 0, fun, &i, 0, NULL);
- WaitForSingleObject (G_hthreadparameter, INFINITE); //wait for the semaphore >0
- ++i;
- }
- WaitForMultipleObjects (Thread_num, handle, TRUE, INFINITE);
- //Destroy the semaphore and key segment
- DeleteCriticalSection (&g_csthreadcode);
- CloseHandle (G_hthreadparameter);
- For (i = 0; i < thread_num; i++)
- CloseHandle (Handle[i]);
- return 0;
- }
- unsigned int __stdcall fun (void *ppm)
- {
- int nthreadnum = * (int *) PPM;
- ReleaseSemaphore (G_hthreadparameter, 1, NULL); //Signal volume + +
- Sleep (50); //some work should
- EnterCriticalSection (&g_csthreadcode);
- ++g_nnum;
- Sleep (0); //some work should
- printf ("Thread number%d global resource value is%d\n", Nthreadnum, G_nnum);
- LeaveCriticalSection (&g_csthreadcode);
- return 0;
- }
Running results such as:
As you can see, semaphores can also solve synchronization problems between threads.
Since the semaphore can calculate the current amount of the resource and determine whether the semaphore is in the trigger state or not triggered based on the current remaining amount compared with 0, the signal volume is widely used. This series of "Seconds to kill multi-threaded tenth" producer consumer issues will use it again to solve the thread synchronization problem, welcome to see.
At this point, the classic thread synchronization problem is all over, the next "Seconds to kill multithreading Nineth Classic multi-threaded synchronization Problem Summary" will be summed up to comb the knowledge points.
Reprint please indicate source, original address: http://blog.csdn.net/morewindows/article/details/7481609
Classic Thread Sync semaphore semaphore