上一节中,我们用CriticalSection方法得到了连续数,其实这主要是CriticalSection所包含的区域与前面的原子操作有类似的功能。但是前面原子的操作没有得到连续的是因为cout部分和原子操作不是连续的,在cout之前有可能有多次的原子操作 所以不是连续的,这个CriticalSection能把cout和++都包含成原子操作。
下面我们看下CreateEvent的两个细小的差别
代码1:
#include <iostream> #include<Windows.h> #include <process.h> HANDLE eve; CRITICAL_SECTION b; int num; unsigned int __stdcall ThreadFun(PVOID pm) { int m=*((int*)pm); SetEvent(eve); ResetEvent(eve); EnterCriticalSection(&b); num++; std::cout<<m<<"说:"<<num<<std::endl; LeaveCriticalSection(&b); return 0; } int main() { const int n =50; HANDLE handle[n]; eve =CreateEvent(NULL,false,false,NULL); InitializeCriticalSection(&b);//旋转锁 旋转4000次 num = 0; int i=0; while(i<10){ handle[i] =(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL); WaitForSingleObject(eve,INFINITE); i++; } WaitForMultipleObjects(n,handle,true,INFINITE); system("pause"); CloseHandle(eve); DeleteCriticalSection(&b); return 0; }
运行结果:
代码二:其他代码一样
unsigned int __stdcall ThreadFun(PVOID pm) { SetEvent(eve); ResetEvent(eve); EnterCriticalSection(&b); num++; std::cout<<*((int*)pm)<<"说:"<<num<<std::endl; LeaveCriticalSection(&b); return 0; }
运行结果:
这里我们就可以看到,其实线程传参传的是地址,线程每次用到这个地址的时候会去读,但是这个值是意外可变的,有个关键字(volatile)一个定义为volatile的变量是说这变量可能会被意想不到地改变,所以每次读地址的时候都会有误差。线程同步的问题。
事件可以由SetEvent()来触发,由ResetEvent()来设成未触发。还可以由PulseEvent()来发出一个事件脉冲
二:互斥量mutex
跟CriticalSection差不多 不能用于主进程与线程同步 代码
#include <iostream> #include<Windows.h> #include <process.h> HANDLE mutex; CRITICAL_SECTION b; int num; unsigned int __stdcall ThreadFun(PVOID pm) { int m =*((int*)pm); OpenMutex(MUTEX_ALL_ACCESS,FALSE,NULL); num++; std::cout<<m<<"说:"<<num<<std::endl; ReleaseMutex(mutex);//触发互斥量 return 0; } int main() { const int n =10; HANDLE handle[n]; LPCWSTR a=(LPCWSTR)(LPCTSTR)"aaa"; mutex =CreateMutex(NULL,false,NULL);//第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量 InitializeCriticalSection(&b);//旋转锁 旋转4000次 num = 0; int i=0; while(i<10){ handle[i] =(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL); WaitForSingleObject(mutex,INFINITE); i++; } WaitForMultipleObjects(n,handle,true,INFINITE); system("pause"); CloseHandle(mutex); DeleteCriticalSection(&b); for (i = 0; i < n; i++) CloseHandle(handle[i]); return 0; }