线程同步的方主要有以下四种法:
1、临界区:通过临界区实现多个线程对同一公共资源或一段代码的串行访问,速度快,适合控制数据的访问。
2、互斥量:通过协调线程共同对一个共享资源的单独访问而设计。
3、信号量:可以控制有限用户对同一资源的的访问而设计;
4、事件:通过通知线程的有一些事件已经发生,从而可以启动后续的任务执行。
在学习多线程的过程中,本人首先解除学习到的是互斥量。
学习互斥量的过程中主要使用到三个函数:
创建互斥量函数:
HANDLE WINAPI CreateMutex(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
_In_ BOOL bInitialOwner,//初始拥有者
_In_opt_ LPCTSTR lpName//互斥量名称
);
释放互斥量函数:
BOOL WINAPI ReleaseMutex(
_In_ HANDLE hMutex
);
信号等待函数:
DWORD WINAPI WaitForSingleObject(
_In_ HANDLE hHandle,
_In_ DWORD dwMilliseconds
);
而有关互斥量的知识如下:
互斥对象属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。
互斥对象包含一个使用数量,一个线程ID和一个计数器。
ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。
在使用互斥量的过程中尤其要注意一下几点:
1 谁拥有谁释放。当某一线程拥有互斥对象时,另外一个线程是不能通过ReleaseMutex函数来释放的,因为在调用ReleaseMutex时系统会首先把互 斥对象拥有者的线程ID与释放互斥对象的线程ID相比对,两个ID不同,对象是得不到释放的。
2某一线程对互斥对象的计数器减为0时,互斥对象才会得到释放;这是别的线程才能重新拥有互斥对象。这就是计数器的作用了。
3 当拥有互斥对象的线程结束时没有释放互斥对象,系统会随着该线程生命周期的结束自动释放其对互斥对象的拥有权,这是其他线程可申请互斥对象 的拥有权。
4如果希望在某一时间内程序只有一个实例获得运行,可以通过命名互斥对象来实现。
主程序实现如下,线程入口函数的实现可参见上一篇。
SetProcessAffinityMask(GetCurrentProcess(),2); //设定运行的CPU
HANDLE handle1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
HANDLE handle2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
// HANDLE handle3=CreateThread(NULL,0,ThreadProc3,NULL,0,NULL);
CloseHandle(handle1);
CloseHandle(handle2);
hMutex=CreateMutex(NULL,true,(LPCTSTR)"tickets");
if(hMutex)
if( ERROR_ALREADY_EXISTS==GetLastError())
{
cout<<"only one instance can be runned!"<<endl;
return;
}
WaitForSingleObject(hMutex,INFINITE);
ReleaseMutex(hMutex);
ReleaseMutex(hMutex);
至于其他多线程同步的方法,还有待学习!