多线程例子_InterlockedExchangeAdd

参考《windows核心编程》(第5版)

有问题的代码

#include <windows.h>
#include <iostream>

using namespace std;

long g_x = 0;

DWORD WINAPI ThreadFunc(LPVOID);

#define MaxCount 20

int main( void )
{
	DWORD threadId;
	HANDLE threadHandle[MaxCount];
	for (int i=0; i<MaxCount;++i)
	{
		threadHandle[i] = CreateThread(NULL, 0, ThreadFunc, 0, 0, &threadId);
	}

	Sleep(100);
	for (int i=0; i<MaxCount;++i)
	{
		CloseHandle(threadHandle[i]);
	}
	
	cout <<g_x<<endl;
	system("pause");
	return 0;
}


DWORD WINAPI ThreadFunc( LPVOID lpParam )
{
	g_x++;
	//InterlockedExchangeAdd(&g_x, 1);
	return TRUE; 
}
潜在风险

g_x++的汇编代码如下

mov         eax,dword ptr [g_x (417148h)] 
add         eax,1 
mov         dword ptr [g_x (417148h)],eax
在多线程环境下可能这样执行

1  mov         eax,dword ptr [g_x (417148h)] 
2  add         eax,1 

3  mov         eax,dword ptr [g_x (417148h)] 
4  add         eax,1 
5  mov         dword ptr [g_x (417148h)],eax

设g_x为1

在A线程中

1句时eax为1

2句时eax为2

到3句时 切换到B线程

在另一线程中

3句时eax为1

4句时eax为2

5句时g_x为2

当切换到A线程中时,继续执行

mov dword ptr[g_x(417147h)],eax

A线程中的eax为2

则g_x为2

原打算为3


解决方法

#include <windows.h>
#include <iostream>

using namespace std;

long g_x = 0;

DWORD WINAPI ThreadFunc(LPVOID);

#define MaxCount 20

int main( void )
{
	DWORD threadId;
	HANDLE threadHandle[MaxCount];
	for (int i=0; i<MaxCount;++i)
	{
		threadHandle[i] = CreateThread(NULL, 0, ThreadFunc, 0, 0, &threadId);
	}

	Sleep(100);
	for (int i=0; i<MaxCount;++i)
	{
		CloseHandle(threadHandle[i]);
	}
	
	cout <<g_x<<endl;
	system("pause");
	return 0;
}


DWORD WINAPI ThreadFunc( LPVOID lpParam )
{
	//g_x++;
	InterlockedExchangeAdd(&g_x, 1);
	return TRUE; 
}

InterlockedExchangeAdd函数原型为

LONG __cdecl InterlockedExchangeAdd(
  _Inout_  LONG volatile *Addend,
  _In_     LONG Value
);
参数

Added  变量的地址

Value  增量值

此函数保证递增值操作以原子方式进行。注意,我们必须保证传给此函数的变量地址是经过对齐的,否则此函数可能会失败。(可以使用C函数_aligned_malloc函数)。





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值