注:本文中所使用的是C++的示例.
如果程序启动了多个线程,那么就存在多个线程对同一资源进行抢占的问题。在单线程的应用程序中,读取统一资源不会出现意想不到的事情,但是对于多个线程的程序,同时操作同一个资源的时候就会出现我们不期望的结果.为了解决这一问题,提出了线程同步的概念.
· 线程同步的基本方法
线程同步的基本方法有很多,最常用的有互斥(CMutex)、临界(CriticalSection)、信号量(Semaphore)、事件(Event)等。这4中方法分别在Win32和MFC两种方式下个有一种实现,MFC中其实是对win32下的封装,使用起来较为方便。
互斥(CMutex) :
示例代码下载:(VC 6.0)工程:
解压密码 yscode
http://pan.baidu.com/s/1kTJVVOb
互斥 就是一个线程对共享资源进行访问时排斥其他的线程。在Win32中过CreateMutex进行创建,在程序运行的时候只有拥有互斥对象的线程才有访问资源的权利。只有当拥有互斥对象的线程通过ReleaseMutex函数交出互斥对象,其他线程才能拥有对资源的访问权利.在MFC中,直接通过CMutex创建对象,通过CMeutex::Lock()和CMutex::Unlock()函数进行锁定和解锁.
//下面是一个 控制台的 同步示例代码,其中 SIGN 是一个BOOL值,为TRUE的时候开启同步,为FALSE的时候关闭线程同步,你可以对比一下不同情况下的输出.
//*********************这一段是使用Win32的方法 #include <windows.h> #include <iostream> using namespace std; //!!!!!!!!!!!!!!!!通过一个标记,开启或者关闭同步,来查看效果 BOOL SIGN = TRUE; //一个数组用于打印显示使用 int Arry[20]; //用于线程同步的互斥体句柄 HANDLE hMutex = NULL; //*********************************线程1,对数组内的数值进行赋值0~19 DWORD CALLBACK ThreadProc1(LPVOID lp) { //等待互斥体,如果没有拥有互斥体将会等待 INFINITE ms时间 if(SIGN) WaitForSingleObject(hMutex,INFINITE); //让线程先睡一下,让线程2有机会执行 //如果没有同步的话,线程2是不会等待1完成的,那么输出的数值是不对的 Sleep(100); for (int i=0;i<20;i++) { Arry[i] = i; } if(SIGN) ReleaseMutex(hMutex);//释放互斥体 return 0; } //*********************************线程2,打印数组 DWORD CALLBACK ThreadProc2(LPVOID lp) { //等待互斥体,如果没有拥有互斥体将会等待 INFINITE ms时间 if(SIGN) WaitForSingleObject(hMutex,INFINITE); for (int i=0;i<20;i++) { cout<<"Arr["<<i<<"]: "<<Arry[i]<<endl; } if(SIGN) ReleaseMutex(hMutex);//释放互斥体 return 0; } int main() { memset(Arry,0xFF,sizeof(Arry));//初始化数组 //创建一个互斥体,参数2指定 没有线程拥有这个互斥体 if(SIGN) hMutex = CreateMutex(NULL,FALSE,NULL); //开始线程1 DWORD tid = 0; HANDLE hThread = INVALID_HANDLE_VALUE; //开启线程1 hThread = CreateThread(0,0,ThreadProc1,0,0,&tid); if(hThread!=INVALID_HANDLE_VALUE){CloseHandle(hThread);} //开启线程2 hThread = CreateThread(0,0,ThreadProc2,0,0,&tid); if(hThread!=INVALID_HANDLE_VALUE){CloseHandle(hThread);} //防止主线程退出 while(TRUE){ Sleep(1000); } return 0; }
//下面是一个使用MFC的方法写的互斥体同步,由于是在控制台写的,所以要引入MFC的头文件,并且需要将工程的属性设置为使用MFC的静态库/共享库
//*******************************************这一段是使用的是MFC的方法
//因为我这里使用的是 控制台的程序,要使用MFC的话 //引入MFC的头文件,还有就是工程属性 要使用 MFC静态库或者动态库才行 #include <AfxWin.h> #include <afxmt.h> #include <iostream> using namespace std; //通过一个标记,开启或者关闭同步,来查看效果 BOOL SIGN = TRUE; //一个数组用于打印显示使用 int Arry[20]; //创建一个CMutex的互斥体 CMutex MuTex(FALSE,NULL); //*********************************线程1,对数组内的数值进行赋值0~19 DWORD CALLBACK ThreadProc1(LPVOID lp) { if(SIGN) MuTex.Lock();//等待互斥体,如果没有拥有互斥体将会等待 INFINITE ms时间 //让线程先睡一下,让线程2有机会执行 //如果没有同步的话,线程2是不会等待1完成的,那么输出的数值是不对的 Sleep(100); for (int i=0;i<20;i++) { Arry[i] = i; } if(SIGN) MuTex.Unlock(); return 0; } //*********************************线程2,打印数组 DWORD CALLBACK ThreadProc2(LPVOID lp) { if(SIGN) MuTex.Lock(); for (int i=0;i<20;i++) { cout<<"Arr["<<i<<"]: "<<Arry[i]<<endl; } if(SIGN) MuTex.Unlock(); return 0; } int main() { memset(Arry,0xFF,sizeof(Arry));//初始化数组 //开始线程1 DWORD tid = 0; HANDLE hThread = INVALID_HANDLE_VALUE; //开启线程1 hThread = CreateThread(0,0,ThreadProc1,0,0,&tid); if(hThread!=INVALID_HANDLE_VALUE){CloseHandle(hThread);} //开启线程2 hThread = CreateThread(0,0,ThreadProc2,0,0,&tid); if(hThread!=INVALID_HANDLE_VALUE){CloseHandle(hThread);} //防止主线程退出 while(TRUE){ Sleep(1000); } return 0; }
示例代码下载:(VC 6.0)工程:
解压密码 yscode
http://pan.baidu.com/s/1kTJVVOb
本文出自 悠然品鉴,转载请注明出处:http://www.youranshare.com/blog/sid/38.html