"Multithreading" Learning 2

Source: Internet
Author: User
Tags strtok

Pre-Knowledge:

__stdcallIs function calling convention, the function calling convention mainly constrains two things: 1. Parameter passing Order 2. WHO (calling function or called function) cleans up common function calling conventions for call stacks: stdcall cdecl fastcall thiscall naked Call __stdcallRepresents 1. The parameter is pressed from right to left into the stack 2. The function is called by the caller to modify the stack 3. The function name (at the compiler level) is automatically preceded by an underscore, followed by an @ symbol, followed by the size of the parameter in the Win32 application, macro Apientry,winapi, all means _ StdCall, very common.

---------------------------------------------------------------------------------------

Transfer from http://blog.csdn.net/morewindows/article/details/7421759

CreateThread The () function is a Windows-provided API interface, and in the C + + language There is another thread-creating function, _beginthreadex(), which has been mentioned in many books (including "Windows core Programming") as much as possible using _ Beginthreadex() instead of using CreateThread(), why is this? 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     (errno) {...  //  error handling code   

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 calls 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 errnothat has been modified by the B thread. This situation must be avoided! Because not only is this one variable problematic, other like strerror(), strtok(), tmpnam(),gmtime(),asctime( Functions such as these can also encounter data coverage problems 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 _beginthreadex(), the C + + Runtime library function. The source code for the _beginthreadex() function is listed below (I added some comments in this code) so that the reader can better understand the _beginthreadex() function and CreateThread( ) The difference between the functions.

//_beginthreadex Source finishing by Morewindows (http://blog.csdn.net/MoreWindows )_mcrtimp uintptr_t __cdecl _beginthreadex (void*security, unsigned stacksize, unsigned (__clr_or_std_call* Initialcode) (void*),    void*argument, unsigned createflag, unsigned*thrdaddr)          {_ptiddata ptd; //Pointer to per-thread data see note 1uintptr_t THDL;//thread handle Threading handleUnsignedLongErr =0L;//Return from GetLastError ()unsigned Dummyid;//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 the thread's _tiddata block that is the CRT data area see note 2_INITPTD (ptd, _GETPTD ()ptlocinfo); //set the other data in the _TIDDATA structure so that the _tiddata block is associated with the thread. PTD->_INITADDR = (void*) Initialcode;//thread function AddressPtd->_initarg = argument;//thread parameters passed inPtd->_thandle = (uintptr_t) (-1); #ifDefined (_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 a 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) Thrdad DR))= = (uintptr_t)0) {Err=GetLastError (); GotoError_return; }    //Good return    return(THDL);//The thread is created successfully, returning 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. //Reclaim the _tiddata block 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. The _ptiddata in _ptiddata ptd is a struct-body pointer. In the mtdll.h file is defined:

typedef struct _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 the GETPTD () in this code is:

/ * Return address of per-thread CRT data * /

_ptiddata __cdecl _getptd(void);

The _INITPTD () is described as follows:

/ * Initialize a per-thread CRT data block * /

void __cdecl _initptd (_inout_ _ptiddata _ptd, _in_opt_ pthreadlocinfo _locale);

The CRT in the note (C Runtime Library) is the standard C runtime library.

Note 3. The _getdomain () function code in the IF (!_getdomain (&ptd->__initdomain)) can be found in the Thread.c file, whose primary function is to initialize the COM environment.

From the source code above, the_beginthreadex () function allocates and initializes a _tiddata block when a new thread is created. 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 associates the _tiddata block with itself. The new thread then calls 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 in the _tiddata 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, try to use _beginthreadex() instead of 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:

//To create a multiple child thread instance#include <stdio.h>#include<process.h>#include<windows.h>//Child thread FunctionsUnsignedint__stdcall Threadfun (PVOID pM) {printf ("thread ID number%4d child thread said: Hello world\n", GetCurrentThreadID ()); return 0;}//The 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\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;}

Each sub-thread in the diagram says the same sentence, not very good-looking. Can you come up with a thread count function, that is, the first child thread output 1, the second child thread output 2, the third child thread output 3, ... It seems very simple to implement this function-each child thread increments and outputs a global variable. The code is as follows:

//Count of Sub-threads#include <stdio.h>#include<process.h>#include<windows.h>intG_ncount;//Child thread FunctionsUnsignedint__stdcall Threadfun (PVOID pM) {G_ncount++; printf ("a child thread with a thread ID number of%4d%d\n", GetCurrentThreadID (), g_ncount); return 0;}//The main function , the so-called main function is actually the main thread execution function. intMain () {printf ("sub-thread count \ n"); printf ("--by Morewindows (http://blog.csdn.net/MoreWindows)--\n\n"); Const intThread_num =Ten;    HANDLE Handle[thread_num]; G_ncount=0;  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;}

The answer is wrong, although this is logically correct, but in a multithreaded environment this will cause serious problems, the next "second multi-threaded third atomic Operation Interlocked series function" will show you the wrong results (possibly very unexpected) and explain the results of the detailed reasons.

"Multithreading" Learning 2

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.