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号