WIN32汇编语言教程:第12章 多线程 · 12.4 线程间的同步(4)
mov dwCounter2,0 xor ebx,ebx .while ebx < 20 invoke CreateThread,NULL,0,\ offset _Counter,NULL,\ NULL,addr @dwThreadID invoke CloseHandle,eax inc ebx .endw invoke SetTimer,hWnd,1,500,NULL .endif .endif ;******************************************************************** .elseif eax == WM_CLOSE .if ! dwThreads invoke DeleteCriticalSection,addr stCS invoke EndDialog,hWnd,NULL .endif ;******************************************************************** .elseif eax == WM_INITDIALOG push hWnd pop hWinMain invoke GetDlgItem,hWnd,IDOK mov hWinCount,eax invoke InitializeCriticalSection,addr stCS ;******************************************************************** .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;#################################################################### start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,eax,DLG_MAIN,NULL,\ offset _ProcDlgMain,NULL invoke ExitProcess,NULL ;#################################################################### end start
程序在 .data?段中定义了一个CRITICAL_SECTION结构并在WM_INITDIALOG消息中使用InitializeCriticalSection函数对它初始化。在线程函数中对计数值进行递增操作的前后分别使用EnterCriticalSection和LeaveCriticalSection函数:
invoke EnterCriticalSection,addr stCS inc dwCounter1 mov eax,dwCounter2 inc eax mov dwCounter2,eax invoke LeaveCriticalSection,addr stCS
另外,在显示计数结果的WM_TIMER消息中也进行同样的操作:
invoke EnterCriticalSection,addr stCS invoke SetDlgItemInt,hWinMain,IDC_COUNTER1,dwCounter1,FALSE invoke SetDlgItemInt,hWinMain,IDC_COUNTER2,dwCounter2,FALSE invoke LeaveCriticalSection,addr stCS
这是为了防止在两句SetDlgItemInt之间其他线程改变计数值造成显示结果的不统一。修改后经过编译链接后再运行,就可以发现两个计数器的值永远保持统一了!
读者还可以发现一个现象:同样的时间内,正确同步的程序的计数值要远远小于同步不正确的程序,比如在笔者的计算机上,同样是运行10秒,这个程序只能计数2 132 586次,与前述例子的783 189 430次相比,前者不及后者的3‰,这说明花在等待上的时间实在是太多了,但这是多线程程序为了保持数据同步所必须付出的代价。
上页:第12章 多线程 · 12.4 线程间的同步(3) 下页:第13章 进程控制 · 13.1 环境变量和命令行参数(1)
第12章 多线程
版权所有 © 云南伯恩科技 证书:粤ICP备09170368号