秒杀多线程第三篇 原子操作 Interlocked系列函数 .
参考博客:http://blog.csdn.net/morewindows/article/details/7429155
本想以该博客的指示编写程序找出漏洞,但是却没有发现异常
//创建多子个线程实例 #include <stdio.h> #include <process.h> #include <windows.h> volatile long g_nLoginCount=0; //登录次数 const int THREAD_NUM = 55; //启动线程数 //子线程函数 unsigned int __stdcall ThreadFun1(PVOID pM) { Sleep(100); g_nLoginCount++; printf("线程号是:%4d 该线程说:%d\n",GetCurrentThreadId(),g_nLoginCount); Sleep(50); return 0; } int main() { int num=20;//循环20次,以便找出错误 while (num--) { HANDLE handle[THREAD_NUM]; for(int i=0;i<THREAD_NUM;i++) handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun1, NULL, 0, NULL); WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); printf("%d\n",g_nLoginCount); } return 0; }
运行参考 博客的程序找出了漏洞
1 #include <stdio.h> 2 #include <windows.h> 3 volatile long g_nLoginCount; //登录次数 4 unsigned int __stdcall Fun(void *pPM); //线程函数 5 const DWORD THREAD_NUM = 50;//启动线程数 6 DWORD WINAPI ThreadFun(void *pPM) 7 { 8 Sleep(100); //some work should to do 9 g_nLoginCount++; 10 Sleep(50); 11 return 0; 12 } 13 int main() 14 { 15 printf(" 原子操作 Interlocked系列函数的使用\n"); 16 printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); 17 18 //重复20次以便观察多线程访问同一资源时导致的冲突 19 int num= 20; 20 while (num--) 21 { 22 g_nLoginCount = 0; 23 int i; 24 HANDLE handle[THREAD_NUM]; 25 for (i = 0; i < THREAD_NUM; i++) 26 handle[i] = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL); 27 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); 28 printf("有%d个用户登录后记录结果是%d\n", THREAD_NUM, g_nLoginCount); 29 } 30 return 0; 31 }
运行结果:
Windows系统为我们提供了一些以Interlocked开头的函数来完成这一任务(下文将这些函数称为Interlocked系列函数)
下面列出一些常用的Interlocked系列函数:
1.增减操作
LONG__cdeclInterlockedIncrement(LONG volatile* Addend);
LONG__cdeclInterlockedDecrement(LONG volatile* Addend);
返回变量执行增减操作之后的值。
LONG__cdec InterlockedExchangeAdd(LONG volatile* Addend, LONGValue);
返回运算后的值,注意!加个负数就是减。
2.赋值操作
LONG__cdeclInterlockedExchange(LONG volatile* Target, LONGValue);
Value就是新值,函数会返回原先的值。
只将支线程的服务函数换成Interlocked系列函数即可
1 DWORD WINAPI ThreadFun(void *pPM) 2 { 3 Sleep(100); //some work should to do 4 // g_nLoginCount++; 5 InterlockedIncrement((LPLONG)&g_nLoginCount); 6 Sleep(50); 7 return 0; 8 }