Synchronous Mechanism and use of Windows synchronous Functions

Source: Internet
Author: User
Tags semaphore

[Switch]Synchronous Mechanism and use of Windows synchronous Functions

Author:Simahao

Link: http://blog.csdn.net/simahao/archive/2005/07/15/425420.aspx

 

This article is suitable for users who are familiar with multithreading and want to learn thread synchronization.

Recently, due to the use of multithreading, it is inevitable to use synchronization between threads. I have a preliminary understanding of some common synchronous functions and mechanisms in windows, I also wrote some small examples for verification. Of course, there are inevitable errors and omissions. I hope the experts can point out the shortcomings for me. Thank you very much.

Directory
Critical Section
Binary mutex
Event 3
Four semaphores
Appendix 5

 

Critical Section

The use of the critical section should be relatively simple in thread synchronization. Simply put, it is easier to understand than other methods described later. For example, there is a global variable (public resource) and two threads will perform write and read operations on it. If we do not control it here, will produce unexpected results. Suppose thread a is adding 1 to the global variable and printing it on the screen, but then switching to thread B, thread B adds 1 to the global variable and switches to thread, at this time, the result printed by thread A is not the result that the program wants, and an error occurs. The solution is to set a region to lock thread a When manipulating the global variable. If thread B wants to manipulate the global variable, it will wait for thread a to release the lock, this is the concept of critical section.


Usage:
Critical_section Cs;
Initializecriticalsection (& CS );
Entercriticalsection (& CS );
...
Leavecriticalsection (& CS );
Deletecriticalsection (& CS );
# Include "stdafx. H"
# Include <windows. h>
# Include <process. h>
# Include <iostream>
Using namespace STD;

/*************************************** *************************
* When using the critical section, note that each shared resource has a critical_section.
* To access multiple shared variables at a time, ensure that the access sequence of each thread is consistent.
* Consistency. A deadlock is likely to occur. For example:
* Thread one:
* Entercriticalsection (& C1)
* Entercriticalsection (& C2)
*...
* Leave...
* Leave...
*
* Thread two:
* Entercriticalsection (& C2 );
* Entercriticalsection (& C1 );
*...
* Leave...
* Leave...
* In this case, a deadlock occurs. The order of thread 2 entering the critical section is the same as that of thread 1.
**************************************** ************************/

Const int max_threadnums = 4; // Number of threads generated
Critical_section Cs; // critical section
Handle event [max_threadnums]; // Save the returned handle of createevent
Int critical_value = 0; // share resources

Uint winapi threadfunc (void * Arg)
{
Int thread = (INT) ARG;
For (INT I = 0; I <5; I ++)
{
Entercriticalsection (& CS );
Cout <"Thread" <thread <"";

Critical_value ++;
Cout <"critical_value =" <critical_value <Endl;
Leavecriticalsection (& CS );
}
Setevent (event [thread]);
Return 1;
}

Int main (INT argc, char * argv [])
{
Cout <"This Is A critical_section test program" <Endl;
Handle hthread;
Uint uthreadid;
DWORD dwwaitret = 0;

Initializecriticalsection (& CS );

For (INT I = 0; I <max_threadnums; I ++)
{
Event [I] = createevent (null, true, false ,"");
If (event [I] = NULL)
{
Cout <"create event" <I <"failed with Code :"
<Getlasterror () <Endl;
Continue;
}
Hthread = (handle) _ beginthreadex (null, 0, threadfunc,
(Void *) I, 0, & uthreadid );
If (hthread = 0)
{
Cout <"begin thread" <I <"failed with Code :"
<Getlasterror () <Endl;
Continue;
}
Closehandle (hthread );
}
// Wait for all threads to finish
Dwwaitret = waitformultipleobjects (max_threadnums, event, true, infinite );
Switch (dwwaitret)
{
Case wait_object_0:

Cout <"all the sub thread has exit! "<Endl;
Break;
Default:
Cout <"wait for all the thread failed with Code:" <getlasterror () <Endl;
Break;
}

Deletecriticalsection (& CS );
For (int K = 0; k <max_threadnums; k ++)
{
Closehandle (event [k]);
}
Return 0;
}

 

Binary mutex
Windows API provides a mutex, which is more powerful than the critical section. Maybe you have to ask, what is the difference between this stuff and the critical section? Why is it so powerful? They have the following inconsistencies:
1. The critical section is a local object, while the mutex section is a core object. Therefore, waitforsingleobject cannot wait for the critical section.
2. critical section is fast and efficient, while mutex is much slower than it.
3. the critical section uses various threads in a single process, and mutex can be applied to different processes because it can have a name. Of course, it can also be applied to different threads in the same process.
4. The critical section cannot detect whether a thread is released, and mutex generates an abandoned message after a thread ends. At the same time, mutex can only be released by the thread that owns it. The following are two examples of the application mutex. One is that the program can run only one instance. That is to say, if the same program is already running, it cannot run any more; the other is an example of a very classic philosopher's meal problem.


 

Run a single instance:
# Include "stdafx. H"
# Include <windows. h>
# Include <process. h>
# Include <iostream>
Using namespace STD;

// End the program when s or C is input.
Void printinfo (handle & H, char T)
{
Char C;
While (1)
{
Cin> C;
If (C = T)
{
Releasemutex (h );
Closehandle (h );
Break;
}
Sleep (100 );
}
}
Int main (INT argc, char * argv [])
{
// Create a mutex. When the program discovers that this mutex already exists, it is equivalent to openmutex.
Handle hhandle = createmutex (null, false, "mutex_test ");
If (getlasterror () = error_already_exists)
{
Cout <"you had run this program! "<Endl;
Cout <"input C to close this window" <Endl;
Printinfo (hhandle, 'C ');
Return 1;
}
Cout <"program run! "<Endl;
Cout <"input s to exit program" <Endl;

Printinfo (hhandle,'s ');
Return 1;
}

Philosophers:

Const int philosophers = 5; // Number of philosophers
Const int time_eating = 50; // time required for dinner in milliseconds
Handle event [philosophers]; // the array of handles that the master thread maintains synchronization with the worker thread
Handle mutex [philosophers]; // mutex array, which is equivalent to public resource chopsticks
Critical_section Cs; // control the printed critical zone variable

Uint winapi threadfunc (void * Arg)
{
Int num = (INT) ARG;

DWORD ret = 0;
While (1)
{
Ret = waitformultipleobjects (1, mutex, true, 1000 );
If (ret = wait_timeout)
{
Sleep (100 );
Continue;
}
Entercriticalsection (& CS );
Cout <"philosopher" <num <"eatting" <Endl;
Leavecriticalsection (& CS );
Sleep (time_eating );
Break;
}
// Set the time to signal
Setevent (event [num]);
Return 1;
}
Int main (INT argc, char * argv [])
{
Handle hthread;
Initializecriticalsection (& CS );
// Create threads cyclically
For (INT I = 0; I <philosophers; I ++)
{
Mutex [I] = createmutex (null, false ,"");
Event [I] = createevent (null, true, false ,"");
Hthread = (handle) _ beginthreadex (null, 0, threadfunc, (void *) I, 0, null );
If (hthread = 0)
{
Cout <"create thread" <I <"failed with Code :"
<Getlasterror () <Endl;
Deletecriticalsection (& CS );
Return-1;
}
Closehandle (hthread );
}

// Wait until all philosophers finish eating
DWORD ret = waitformultipleobjects (philosophers, event, true, infinite );
If (ret = wait_object_0)
{
Cout <"all the philosophers had a dinner! "<Endl;
}
Else
{
Cout <"waitformultipleobjects failed with Code:" <getlasterror () <Endl;
}
Deletecriticalsection (& CS );
For (Int J = 0; j <philosophers; j ++)
{
Closehandle (mutex [J]);
}
Return 1;
}

 

Event 3
The feature of an event object is that it can be applied to overlapped I/0. For example, there are two models in socket programming, one is overlapping I/0, one is that event synchronization can be used to complete ports. It is also the core object, so it can be waited by functions such as waitforsingleobje; the event can have a name, so it can be enabled by other processes. I have used event in the previous examples. I will not talk about it here. refer to the previous example.

 

Four semaphores
The concept of semaphore may be more difficult to understand than mutex. First, let me explain how to create a semaphore function, because I didn't know it very quickly at the beginning, and maybe I still have some misunderstandings, if any error occurs, please give me more advice.
Createsemaphore (
Lpsecurity_attributes l1_maphoreattributes, // SD
Long linitialcount, // initial count
Long lmaximumcount, // maximum count
Lptstr lpname // Object Name
)
The first parameter is security, and the default security option null can be used. The second and third parameters are two long-type values. What do they mean? Lmaxinumcount indicates the maximum semaphore value, which must be greater than zero. For example, if the value is 5, five processes or threads can be used. If the sixth process or thread is to be used, it must enter the waiting queue to wait for a process or thread to release resources. Linitalcount indicates the initial value of the semaphore. It must be greater than or equal to zero and less than or equal to lmaximumcount. If linitialcount = 0 & lmaximumcount = 5, it indicates that all current resources have been used. If a process or thread wants to use it, the semaphore will become-1, this process or thread enters the waiting queue until a process or thread executes releasemutex. If linitialcount = 5 & lmaximumcount = 5, it indicates that the current semaphore can be used by a process or thread for five times, and then wait. If initialcount = 2 & maximumcount = 5 is not common, it indicates that you can call createsemaphore or opensemaphore twice. If you call it again, it enters the waiting state. The last parameter indicates the name of the semaphore, so that opensemaphore can be used across processes. I have said so much, but I do not know whether it means that there is no ~


Taking an example, Popo now seems to have only three instances running on the local machine. The mutex we mentioned earlier allows the program to run only one instance, below I use the semaphores mechanism to make the program run three instances like Popo.

# Include "stdafx. H"
# Include <windows. h>
# Include <iostream>
Using namespace STD;

Const int max_runnum = 3; // maximum number of running instances
Void printinfo ()
{
Char C;
Cout <"run program" <Endl;
Cout <"input s to exit program! "<Endl;
While (1)
{
Cin> C;
If (C ='s ')
{
Break;
}
Sleep (10 );
}
}
Int main (INT argc, char * argv [])
{

Handle HSE = createsemaphore (null, max_runnum, max_runnum, "semaphore_test ");
DWORD ret = 0;

If (HSE = NULL)
{
Cout <"createsemaphore failed with Code:" <getlasterror () <Endl;
Return-1;
}


Ret = waitforsingleobject (HSE, 1000 );
If (ret = wait_timeout)
{
Cout <"you have runned" <max_runnum <"program! "<Endl;
Ret = waitforsingleobject (HSE, infinite );
}

Printinfo ();
Releasesemaphore (HSE, 1, null );
Closehandle (HSE );
Return 0;
}

 

Appendix:
Core object
Change Notification
Console input
Event
Job
Mutex
Process
Semaphore
Thread
Waitable Timer

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.