Use C ++ multi-thread programming

Source: Internet
Author: User
I. It is best to use the _ beginthreadex () function in the C ++ Runtime Library to create a process. _ beginthreadex is implemented using createthread, but some processing is done for the c ++ language. For details, see chapter 6th of Windows core programming.
# Pragma once # include <windows. h> # include <process. h> # include <tchar. h ># include <iostream> using namespace STD; Class exampletask {public: void starttask (); unsigned static winapi taskmain (lpvoid PARAM ); // If the thread calls a function as a class member, it must be set to static}; unsigned winapi exampletask: taskmain (lpvoid PARAM) {cout <"thread 1" <Endl; return 0;} void exampletask: starttask () {unsigned uithreadid; // process id_beginthreadex (null, // Security Settings 0, // stacksizetaskmain, // function address (pvoid) (int_ptr) 1, // The parameter list is 0, // 0 indicates immediate operation, create_suspend indicates delayed execution & uithreadid); cout <"start thread 1" <Endl ;} int _ tmain (INT argc, tchar * argv []) {exampletask realtimetask; realtimetask. starttask (); Return 0 ;}

Use remusethread () to continue executing the process: Call the waitforsingleobject () function to let the main thread wait for the sub-thread.

Class threadx {int loopstart; int loopend; int frequent; public: threadx (INT, Int, INT); unsigned static winapi threadstaticentrypoint (lpvoid PARAM); void threadentry (); string threadname;}; threadx: threadx (INT start, int lend, int freq): loopend (LEND), loopstart (start), frequent (freq) {} unsigned winapi threadx:: threadstaticentrypoint (lpvoid PARAM) {threadx * thread = reinterpret_cast <threadx *> (PARAM); thread-> thread Entry (); return 1;} void threadx: threadentry () {for (INT I = loopstart; I <loopend; ++ I) {if (I % frequent = 0) {cout <threadname <"" <I <Endl ;}} cout <threadname <"end" <Endl;} int _ tmain (INT ARGs, tchar * argv []) {threadx * th = new threadx (0, 20, 2 ); handle hth1; unsigned uithreadid; hth1 = (handle) _ beginthreadex (null, // security0, // stack sizethreadx: threadstaticentrypoint, Th, // create_suincluded, // delay Creation, Not created yet. 0 for running or create_suincluded for sushortded & uithreadid); If (hth1 = 0) {cout <"failed to create the process! "<Endl;} th-> threadname =" thread1 "; DWORD dwexitcode; getexitcodethread (hth1, & dwexitcode ); // shocould be still_active = 0x00000103 = 259 printf ("Initial thread 1 exit code = % u \ n", dwexitcode); resumethread (hth1 ); // use resumethread to continue running threadwaitforsingleobject (hth1, infinite); threadx * Th1 = new threadx (, 3); Th1-> threadname = "thread 2"; unsigned th2id; handle HH2 = (handle) _ beginthreadex (NUL L, 0, threadx: threadstaticentrypoint, Th1, create_suincluded, & th2id); getexitcodethread (hth1, & dwexitcode ); // shocould be still_active = 0x00000103 = 259 printf ("Initial thread 2 exit code = % u \ n", dwexitcode); resumethread (hty2);/* (1) the termination of the C ++ main thread also terminates all subthreads created by the main thread. Therefore, if waitforsingleobject is not called in the above Code, the two subthreads t1 and t2 may not be completed or are not executed at all. (2) If a thread is suspended and waitforsingleobject is called to wait for the thread, a deadlock will occur. Therefore, if the above Code does not call resumethread, it will be deadlocked. */Waitforsingleobject (hth1, infinite); closehandle (hth1); closehandle (hth1); Return 0 ;}

Ii. Terminate the thread 1. Wait until the thread executes its own return (Recommended Practice), and then the system will automatically call the _ endthreadex () function to release the process. 2. When _ endthread (0) is called in the process, the process may be stopped if resources are not released, resulting in Memory leakage.
3. How to Implement thread synchronization during Process Synchronization:
User State: atomic operation, critical section
Kernel state: event, semaphore, mutex 1. process synchronization using atomic operations:

/* In the following program, the global variable threaddata is used for synchronization between threads. This value is changed when the subthread ends, the parent thread cyclically determines whether the child thread has ended. When the child thread ends, the parent thread continues the following operations. */Volatile bool threadatom = true; // run the subthread unsigned winapi treadprocess (lpvoid lparam) {for (INT I = 0; I <10; ++ I) {sleep (1000); cout <"sub-thread completion no." <I <"task" <Endl; if (I = 6) {// _ endthreadex (0); // if the process is forcibly terminated, threadatom does not change to false. The main process will have an endless loop} cout <"subthread end" <Endl; threadatom = false; return 1;} int _ tmain (INT argc, tchar * argv []) {unsigned threadid; handle thread = (handle) _ beginthreadex (null, 0, treadprocess, 0, 0, & T Hreadid); If (thread = 0) {cout <"process creation failed! "<Endl ;}while (threadatom) {cout <" the main thread is waiting for the subthread "<Endl; sleep (1600) ;}// waitforsingleobject (thread, infinite ); // use waitforsingleobject to achieve the same purpose. cout <"main thread end" <Endl; closehandle (thread); System ("pause"); Return 0 ;}
The value of threadatom is directly modified because there is only one subthread above. If there are multiple subthreads, interlocked series functions are required for interlockexchange (& threadatom, false ); (For details, see Chapter 8 of Windows core programming ). 2. The critical section ensures that only one thread can access data at a certain time. Only one thread is allowed to access Shared resources at any time. If multiple threads attempt to access the critical section at the same time, all other threads attempting to access the critical section will be suspended and will continue until the thread enters the critical section. After the critical section is released, other threads can continue to seize it and use the atomic method to share resources.
// --------------------------------------------- // In the following example, the process Add increases g_num by 1 each time, and the process Sub reduces the value of // g_num by 2 each time. If g_num is less than 0, the process will be terminated // wait int g_num = 20; critical_section g_cs; unsigned winapi threadadd (lpvoid) {While (true) {If (tryentercriticalsection (& g_cs )) {// try to enter the critical section if (g_num <0) {leavecriticalsection (& g_cs); break;} Sleep (1300); cout <"process add to enter the critical section: g_num = "<g_num <Endl; g_num + = 1; cout <" process add leaves the critical section: g_num = "<g_num <Endl; leavecriticalsection (& g_cs ); // exit critical section} els E {sleep (800); cout <"the critical section is occupied by sub processes. Come back next time" <Endl ;}} cout <"add process ended" <Endl; return 1;} unsigned winapi threadsubtract (lpvoid) {While (true) {tryentercriticalsection (& g_cs); // enter the critical section if (g_num <0) {leavecriticalsection (& g_cs ); break;} Sleep (600); cout <"process Sub enters the critical section: g_num =" <g_num <Endl; g_num-= 2; cout <"process sub leaves the critical section: g_num =" <g_num <Endl; leavecriticalsection (& g_cs ); // exit critical section} cout <"sub process ended" <Endl; return 1 ;} Int _ tmain (INT argc, tchar * argv []) {handlethadd; handlethsub; unsignedthaddid; unsignedthsubid; handler (& g_cs); // initialize the thadd = (handle) variable) _ beginthreadex (null, 0, threadadd, 0, 0, & thaddid); thsub = (handle) _ beginthreadex (null, 0, threadsubtract, 0, 0, & thsubid ); if (thadd = 0) {cout <"An error occurred while creating the Add process! "<Endl;} If (thsub = 0) {cout <" An error occurred while creating the sub process! "<Endl;} waitforsingleobject (thadd, infinite); waitforsingleobject (thsub, infinite); closehandle (thadd); closehandle (thsub); deletecriticalsection (& g_cs ); // release the critical zone variable cout <"main process ended" <Endl; System ("pause"); Return 0 ;}

3. Events)

Event objects can also be synchronized by means of notification operations. In addition, threads in different processes can be synchronized. The semaphore contains several operation primitives:

Createevent () // create a semaphore openevent () // open an event setevent () // reset event waitforsingleobject () // wait for an event waitformultipleobjects () // wait for multiple event waitformultipleobjects function prototype: waitformultipleobjects (in DWORD ncount, // wait for the number of handles in const handle * lphandles, // point to the handle array in bool bwaitall, // whether to completely wait for the sign in dword dwmilliseconds // wait time)

Here is an example:

# Pragma once # include <windows. h> # include <tchar. h> # include <process. h> # include <iostream> # include <string> # include <algorithm> using namespace STD; // threads // two threads collaborate to reverse the string //-----------------------------------------------////////////////////////// //////////////////////////////////////// //////// the following example uses a server thread and client thread to process strings: // The server is waiting for processing at the beginning. When the client has a request, it will first send the request to a shared memory buffer., // And trigger an event, the server thread will view the buffer and process client requests. When the server processes the request //, the client is in the waiting state. //////////////////////////////////////// ////////////////// // Handle g_clientevent; // The client has an event to the server handle g_serverevent; // the server has data to the client string buffer; // the shared memory unsigned winapi serverthread (lpvoid lparam) {waitforsingleobject (g_clientevent, infinite ); // infinite: long wait, cout for almost 50 days <"the server receives the original string:" <buffer <Endl; reverse (buffer. begin (), buffer. end (); cout <"server processing string:" <buffer <Endl; setevent (g_servereven T); Return 0;} unsigned winapi clientthread (lpvoid lparam) {string newbuffer (reinterpret_cast <char *> (lparam); buffer = newbuffer; cout <"client sending string: "<buffer <Endl; setevent (g_clientevent); waitforsingleobject (g_serverevent, infinite); cout <" the client receives the string: "<buffer <Endl; return 0;} int _ tmain (INT argc, tchar * argv []) {string Buf = "reverse the string! "; G_clientevent = createevent (null, // security_attributes structure pointer, which can be nullfalse, // true: After waitforsingleobject, you must manually call resetevent to clear the signal // false: After waitforsingleobject, the system automatically clears the event signal false, // The initial state is null); // The event name g_serverevent = createevent (null, false, false, null); unsigned thid; handle serverth = (handle) _ beginthreadex (null, 0, serverthread, null, 0, & thid); handle clientth = (handle) _ beginthreadex (null, 0, clientthread, (void *) BUF. data (), 0, & thid); sleep (5000); // Let the two processes have time to execute closehandle (clientth); closehandle (serverth); closehandle (g_clientevent ); closehandle (g_serverevent); System ("pause"); Return 0 ;}

4. semaphores (semaphore )//-----------------------------------------------
// Operating system question: Dad puts an apple or orange on the plate, and then notifies his son to come // get an apple and his daughter to get an orange. At the same time, only one person can use a plate. The plate can contain at most one fruit. // ------------------------------------------- # define P (S) waitforsingleobject (S, infinite) // wait for a resource # define V (s) releasesemaphore (s, 1, null) // release a resource handle g_plate; // plate handle g_apple; // Apple handle g_orange; // orange // The son eats the apple unsigned winapi eatapple (lpvoid lprama) {While (true) {P (g_apple); P (g_plate); sleep (100 ); cout <"the son has eaten the apple on the disk" <Endl; V (g_plate);} return 0;} // The daughter has eaten the orange unsigned winapi eatorange (lpvoid lprama) {While (true) {P (g_orange); P (g_plate); sleep (100); cout <"my daughter has eaten oranges on the disk" <Endl; V (g_plate);} return 0;}/* // handle createsemaphore (// psecurity_attribute PSA, // long linitialcount, // number of resources available at the beginning // long lmaximumcount, // maximum number of resources // pctstr pszname); * // main process: dad puts fruit int _ tmain (INT argc, tchar * argv []) {g_plate = createsemaphore (null, null); g_apple = createsemaphore (null, null); g_orange = createsemaphore (null, 0, 1, null); unsigned thid; handle son = (handle) _ beginthreadex (null, 0, eatapple, null, 0, & thid ); handle daughter = (handle) _ beginthreadex (null, 0, eatorange, null, 0, & thid); int input = 0; // enter 0 to exit cout <"to start running: 0 exit, 1 put apple, 2 put orange "<Endl; while (true) {CIN> input; If (input = 0) {break ;} else if (input = 1) {cout <"Dad put an apple on the plate" <Endl; P (g_plate); V (g_apple ); V (g_plate);} else if (input = 2) {cout <"Dad put an orange on the plate" <Endl; P (g_plate ); V (g_orange); V (g_plate);} Sleep (150); cout <"enter 0, 1, 2, and continue to put fruit" <Endl;} closehandle (son ); closehandle (daughter); closehandle (g_plate); closehandle (g_orange); closehandle (g_apple); Return 0 ;}

5. mutex)

Two threads simultaneously write one file:

// ------------------------------------------- // Use mutex to synchronize processes: two processes simultaneously write files // using handle g_mutext; int g_wid = 0; void writefile (char * vlist) {ofstream file ("log.txt", ofstream: APP); If (! File) {cerr <"failed to open the file! "<Endl; return;} file <vlist <Endl; file. close ();} unsigned winapi writer1 (lpvoid lparam) {While (true) {waitforsingleobject (g_mutext, infinite); sleep (1000); char STR [200]; sprintf (STR, "writer1 write: % d", g_wid ++); cout <STR <Endl; writefile (STR); releasemutex (g_mutext);} return 0 ;} unsigned winapi writer2 (lpvoid lparam) {While (true) {waitforsingleobject (g_mutext, infinite); sleep (1000); char STR [200]; sprintf (STR, "writer2 write: % d ", g_wid ++); cout <STR <Endl; writefile (STR); releasemutex (g_mutext);} return 0;} int _ tmain (INT ARGs, tchar * argv []) {g_mutext = createmutex (null, false, null); // second parameter: whether the Creator thread has mutex ownership unsigned thid; handle thw1 = (handle) _ beginthreadex (null, 0, writer1, null, 0, & thid); handle thw2 = (handle) _ beginthreadex (null, 0, writer2, null, 0, & thid ); sleep (10000); // execution time closehandle (thw1); closehandle (thw2); closehandle (g_mutext); Return 0 ;}

Reference

Http://blog.csdn.net/ccing/article/details/6215998

Next, we will discuss thread storage and multi-threaded logstores.



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.