Multi-threaded notes-atomic manipulation interlocked series functions

Source: Internet
Author: User

The front wrote a multi-threaded count function, in order to describe the convenience and code for brevity, only output the final count results to observe the program running results. This is very similar to a site's customer access statistics, each user login with a thread impersonation, the thread runs a variable that represents the Count increment. The program outputs this count at the last value indicating how many users are logged in today. If this value is not equal to the number of threads we start, then this program is problematic.

#include <stdio.h>#include<process.h>#include<Windows.h>volatile LongG_nlogincount;//log the number of logins with a global variableUnsignedint_stdcall Fun (PVOID PM);Const intThread_num =Ten;//The number of threads startedunsignedint_stdcall Threadfun (PVOID PM) {Sleep ( -); G_nlogincount++; Sleep ( -); return 0;}intMain () {G_nlogincount=0;    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); printf ("There are%d users logged in after logging the result is%d\n", Thread_num, G_nlogincount); return 0;}

Program execution Results:

The execution results of this program are unstable, and the results of multiple executions are found to be 8, 9, 10, and so on.

In order to enlarge the problem, can clear see the problem, the number of threads set to 50, the program executes 20 times, to see the results of the program execution:

#include <stdio.h>#include<process.h>#include<Windows.h>volatile LongG_nlogincount;//log the number of logins with a global variableUnsignedint_stdcall Fun (PVOID PM);Const intThread_num = -;//The number of threads startedunsignedint_stdcall Threadfun (PVOID PM) {Sleep ( -); G_nlogincount++; Sleep ( -); return 0;}intMain () {intnum = -;  while(num--) {G_nlogincount=0;        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); printf ("There are%d users logged in after logging the result is%d\n", Thread_num, G_nlogincount); }        return 0;}

Look at the running results of the program:

By amplifying the problem, you can see that the result of the operation is very unstable. A reason is analyzed below.

To solve this problem, first of all to analyze g_nlogincount++ this operation, in the VC6.0 compiler to g_nlogincount++ this sentence to break a breakpoint, and then F5 into the debug state, and then press the Debug Toolbar Disassembly button, This is where the assembly code window appears. Can be returned now a simple self-increment statement in the c\c++ language is actually made up of three assembly code, as shown in:

Explain the following three articles of assembly meaning:

The first assembly reads the value of G_nlogincount from memory into the register EAX.

The second assembly adds the value in the register EAX to 1, and the result is still stored in the register EAX.

The third assembly writes the values in the register EAX back into memory.

In this way, because of the concurrency of the thread execution, it is likely that thread a executes to the second sentence, thread B starts execution, and thread B writes the original value to the register eax, so that the value of thread A's main calculation is modified by thread B. In doing so, the result is unpredictable-it may appear to be 50 or less than 50.

Therefore, when reading and writing a variable in a multithreaded environment, we need a way to ensure that an incremental operation on a value is atomic--that is, non-disruptive, that when a thread performs an atomic operation, the other thread must wait for it to complete before it can begin executing the atomic operation. This hardware-related operation will be complicated, and fortunately, the Windows system provides us with some functions that begin with interlocked (these functions are referred to as interlocked series functions).

Some common interlocked series functions are listed below:

 //  add or subtract operation  LONG WINAPI InterlockedIncrement (LONG volatile  * lpaddend); Long WINAPI interlockeddecrement (long  volatile  *  lpaddend);  //  Returns the value of the variable after the increment or decrement operation is performed.  long WINAPI interlockedexchangeadd (LONG   Volatile  * Addend, LONG Value); //  Returns the value after the operation, note! Adding a negative number is minus.  //  Assignment operation   Long WINAPI InterlockedExchange (long  volatile  * Target, LONG Value); // value is the new value, and the function returns the original value. 

Multithreaded notes-atomic manipulation interlocked series functions

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.