[C + +] Multithreading

Source: Internet
Author: User
Tags function prototype goto strtok

Reprint morewindows: Seconds to kill multi-threaded second article

This article will lead you with multi-threaded first intimate contact, and CreateThread in-depth analysis and _beginthreadex The essential difference, I believe that after reading this article you can easily use multi-threaded and can be smooth and accurate answers to CreateThread _beginthreadex What is the difference between the actual programming should be used CreateThread or _beginthreadex?

The use of multithreading is actually very easy, the main thread of the program will create a child thread and wait for it to run, the child thread will output its thread ID number and then output a classic quote--hello world. The code for the whole program is very brief and only a few lines.

//Simplest to create multithreaded instances#include <stdio.h>#include <windows.h>//Sub-threading functionsDWORD WINAPI Threadfun (lpvoid pM) {printf (the thread ID number of the child thread is:%d\nchild thread output Hello world\ n", GetCurrentThreadID ());return 0; }//main function, the so-called main function is actually the main thread execution function. intMain () {printf ("The simplest to create multithreaded instances\ n"); printf--by Morewindows (http://blog.csdn.net/MoreWindows) --\ n"); HANDLE HANDLE = CreateThread (NULL,0, Threadfun, NULL,0, NULL); WaitForSingleObject (handle, INFINITE);return 0; }

Let's talk about some of the functions in the code below.

The first of the CreateThread

function function: Create thread

CreateThread Prototypes in MSDN:

HANDLE CreateThread (Lpsecurity_attributes lpthreadattributes,//SDsize_t Dwstacksize,//initialstacksizeLpthread_start_routine Lpstartaddress,//threadfunctionLPVOID Lpparameter,//threadargumentDWORD dwCreationFlags,//creationoptionLpdword Lpthreadid//threadidentifier)//lpthreadattributes: A pointer to the structure of the security_attributes type. This parameter is ignored in Windows 98. In Windows NT, NULL uses the default security and cannot be inherited by a thread, otherwise a struct is defined to initialize its bInheritHandle member to true.//dwstacksize, sets the size of the initial stack, in bytes, and if 0, the default is to use the same stack space size as the thread that called the function. In any case, Windows dynamically extends the size of the stack as needed. //lpstartaddress, a pointer to a thread function, in the form of the @ function name, which has no limit, but must be declared in the following form://dword WINAPI function name (LPVOID lpparam), the format is incorrect and will fail to invoke success. //lpparameter: A parameter passed to a thread function, which is a pointer to a struct, null if no arguments are passed. //dwcreationflags: The thread flag equals 0 o'clock indicates that activation is immediate after creation. //lpthreadid: Save the ID of the new thread.  If you do not want to return the thread ID, set the value to null. 

A second WaitForSingleObject

function function: Wait function-Causes the thread to enter a wait state until the specified kernel object is triggered.

Function prototype:

Dwordwinapiwaitforsingleobject (

Handlehhandle,

Dworddwmilliseconds

);

Function Description:

The first parameter is the kernel object to wait for.

The second parameter is the longest waiting time, in milliseconds, such as passing in 5000 for 5 seconds, passing in 0 and returning immediately, and passing in infinite means infinite wait.

Because the thread's handle is not triggered when the thread runs, the threads end up running and the handle is in the triggered state. So you can use WaitForSingleObject () to wait for a thread to end up running.

function return value:

The object is triggered at the specified time, and the function returns WAIT_OBJECT_0. The maximum wait time object has not yet been triggered to return wait_timeout. An error in the incoming parameter will return wait_failed

CreateThread()The function is the API interface provided by Windows, and in the C + + language There is another function to create threads _beginthreadex() , and in many books (including "Windows core Programming") mentioned to use as much as possible _beginthreadex() instead CreateThread() of using, why? Here's how to explore and discover the difference between them.

First of all, from the standard C run-time library and multi-threaded contradiction, the standard C run-time library was implemented in 1970, because there is no one operating system to provide multi-threaded support. Therefore, programmers writing the standard C Runtime library do not consider the use of the standard C Runtime library for multithreaded applications. such as the global variable errno of the standard C runtime library. Many functions in the runtime assign the error designator to the global variable in case of an error, which makes it easy to debug. But if there is a code snippet like this:

if (system("notepad.exe readme.txt"-1)  {      switch(errno)      {          ...//错误处理代码      }  }  

Assuming that a thread a executes the above code after the thread has called system () and the switch () statement has not been called, another thread B is started, and this thread B also invokes the function of the standard C run-time library, unfortunately this function performs an error and writes the error code to the global variable errno. This way, when thread a starts executing the switch () statement, it accesses a errno that has been modified by the B thread. This situation must be avoided! Because not only is this variable problematic, other functions such as strerror (), Strtok (), Tmpnam (), Gmtime (), and Asctime () can also encounter this data overwrite problem caused by multiple thread access modifications.

To solve this problem, the Windows operating system provides a solution-each thread will have its own dedicated piece of memory to be used by all the required functions in the standard C run-point library. and the creation of this area of memory is the responsibility of the C + + Runtime library function _beginthreadex() . _beginthreadex()the source code for the function is listed below (I added some comments in this code) so that the reader can better understand the _beginthreadex() difference between functions and functions CreateThread() .

//_beginthreadex Source collation by Morewindows (http://blog.csdn.net/MoreWindows)_mcrtimp uintptr_t __cdecl _beginthreadex (void*security,unsignedStackSizeunsigned(__clr_or_std_call * initialcode) (void*),void* Argument,unsignedCreateflag,unsigned*THRDADDR) {_ptiddata ptd;//pointer to Per-thread data See note 1uintptr_t THDL;//thread handle thread handle    unsigned LongErr =0L;//return from GetLastError ()    unsignedDummyid;//dummy returned thread ID threading ID number          //Validation section Check if Initialcode is null_validate_return (Initialcode! = NULL, EINVAL,0);//initialize flsgetvalue function pointer__set_flsgetvalue ();//allocate and initialize a PER-THREAD data structure for the to-be-created thread.     //corresponds to the new _tiddata structure and assigns to the _ptiddata pointer.     if(ptd = (_ptiddata) _calloc_crt (1,sizeof(struct_tiddata))) = = NULL)GotoError_return;//Initialize the Per-thread data    //Initialize thread _tiddata block that is CRT data area see note 2_INITPTD (ptd, _GETPTD ()->ptlocinfo);//Set other data in the _TIDDATA structure so that the _tiddata block is associated with the thread. PTD-&GT;_INITADDR = (void*) Initialcode;//thread function addressPtd->_initarg = argument;//Incoming thread parametersPtd->_thandle = (uintptr_t) (-1);#if defined (_M_CEE) | | defined (mrtdll)    if(!_getdomain (& (Ptd->__initdomain)))//See note 3{GotoError_return; }#endif//Defined (_M_CEE) | | defined (mrtdll)          //Make sure Non-null thrdaddr are passed to CreateThread    if(thrdaddr = = NULL)//Determine if the thread ID number needs to be returnedTHRDADDR = &dummyid;//Create The new thread using the parameters supplied by the caller.     //_beginthreadex () will eventually call CreateThread () to request the creation of a thread from the system    if(THDL = (uintptr_t) CreateThread ((lpsecurity_attributes) security, StackSize,                      _threadstartex, (LPVOID) ptd, Createflag, (Lpdword) thrdaddr) = = (uintptr_t)0) {err = GetLastError ();GotoError_return; }//good return    return(THDL);//Thread creation succeeds, returns a handle to the new thread.           //error returnError_return://either ptd is NULL, or it points to the no-longer-necessary block    //calloc-ed for the _tiddata struct which should now is freed up.     //Recovery of _tiddata blocks requested by _CALLOC_CRT ()_FREE_CRT (PTD);//Map the error, if necessary.     //Note:this routine returns 0 for failure, just like the Win32    //API CreateThread, but _beginthread () returns-1 for failure.     //Correction error code (can call GetLastError () get error code)    if(Err! =0L) _dosmaperr (ERR);return((uintptr_t)0);//Returns a valid handle with a null value}

Explain the next part of the code:

Note 1. _ptiddataptd; _ptiddata is a pointer to the struct body. In the mtdll.h file is defined:

?typedefstruct_tiddata * _ptiddata

Microsoft commented on it as Structure for each thread‘s data . This is a very large structure, with a lot of members. This article is not listed because of the limitation of space.

Note 2. _initptd(ptd, _getptd()->ptlocinfo);Microsoft's description of GETPTD () in this code is:

?/* return address of per-thread CRT data */

?_ptiddata __cdecl_getptd(void);

The _initptd() explanations are as follows:

?/* initialize a per-thread CRT data block */

?void__cdecl_initptd(_Inout_ _ptiddata _Ptd,_In_opt_ pthreadlocinfo _Locale);

The CRT (C Runtime Library) standard C Runtime Library is in the comments.

Note 3. if(!_getdomain(&(ptd->__initDomain)))the _getdomain () function code in the THREAD.C file can be found in the main function of initializing the COM environment.

From the source code above, the _beginthreadex() function allocates and initializes a block when a new thread is created _tiddata . This _tiddata block is naturally used to store some data that needs to be held exclusively by threads. In fact, when the new thread runs, it first _tiddata associates the block with itself. The new thread then invokes the standard C run-time library function, such as strtok (), and then takes the address of the _tiddata block and then stores the data that needs to be protected _tiddata in the block. This way each thread will only be able to access and modify its own data without tampering with other threads ' data. Therefore, if you have a function in your code that uses the standard C run-time library _beginthreadex() , try to use it instead CreateThread() . believe that when reading here, you will have a very deep impression of this short sentence, if the interviewer asked, you can also smooth and accurate answer ^_^.

Next, a program similar to the one above uses CreateThread () to create a child thread that outputs "Hello world", using _beginthreadex () to create multiple child threads:

//Create multiple child thread instances#include <stdio.h>#include <process.h>#include <windows.h>//Sub-threading functionsunsigned int__stdcall Threadfun (PVOID pM) {printf (The thread ID number is%4dthe sub-thread says: Hello World\ n", GetCurrentThreadID ());return 0; }//main function, the so-called main function is actually the main thread execution function. intMain () {printf ("Create multiple child thread instances\ n"); printf--by Morewindows (http://blog.csdn.net/MoreWindows) --\ n");Const intThread_num =5; HANDLE Handle[thread_num]; for(inti =0; i < Thread_num; i++) Handle[i] = (handle) _beginthreadex (NULL,0, Threadfun, NULL,0, NULL); WaitForMultipleObjects (Thread_num, handle, TRUE, INFINITE);return 0; }

[C + +] Multithreading

Related Article

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.