没人看c我就不写c了吗?Too naive.
互斥对象又叫做mutex,属于内核对象,能够确保线程对于单个资源的互斥访问权,互斥对象包含一个数量,一个线程ID,和一个计数器。其中ID用于标识系统中哪个线程当前占有互斥对象,计数器指明当前线程拥有过互斥对象的次数。
互斥对象保护了共享资源,确保共享资源在一个线程访问完毕之后才能被其他线程访问。线程对于共享资源进行操作前要先申请得到互斥对象的所有权,如果得不到,可以选择直接放弃返回也可以选择一直等待,知道其他线程释放了mutex所有权或者时间到;如果申请到了,就可以对共享资源进行访问,访问完毕后需要释放对于mutex的所有权,有时候,爱情也是这样。
要用到互斥对象的话,你先得创建互斥对象。创建互斥对象的线程可以选择拥有该对象的所有权,也可以选择不拥有。如果是后者的话,则该互斥对象处于有信号状态,可以被其他线程申请所有权。一旦某线程申请得到了所有权,那么mutex又没有了信号,其他线程还想要申请所有权就需要等待,当它释放了互斥对象的所有权,那么又会有信号。有时候,爱情也是这样。
对于互斥对象的操作,主要就是建立、申请和释放,本文我们先来介绍一下互斥对象的创建。
先这样8,我晚点来填这个坑。
今天看了一个小时的锤子科技的发布会,我觉得海星。
1.互斥对象的创建:
为了创建互斥对象,需要调用函数CreateMutex,该函数可以创建或者打开一个命名的或匿名的互斥对象,然后程序就可以利用该互斥对象完成线程的同步。
原型:
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,
Bool binitialOwner,
LPCTSTR lpName)
该函数有三个参数:
第一个参数我们在前面提到过,一般而言赋值为NULL就行了,使用默认的安全性。
第二个参数:BOOL类型,指定互斥对象初始的拥有者。该值为真,则获得所有权,否则不获得。
第三个参数:指定互斥对象的名称,如果是NULL就是创建一个匿名的对象。
如果调用成功,函数返回所创建的互斥对象的句柄。
比如Handle hMutex=CreateMutex(NULL,TRUE,"ticket");这句话就创建了一个叫做ticket的互斥对象,对象的所有权归创建它的线程。
如果创建的是命名的互斥对象,并且在CreateMutex函数调用之前,该命名的互斥对象存在,那么该函数将会返回已经存在的这个互斥对象的句柄。
2.申请互斥对象的所有权:
可以用到WaitForSingleObject函数来实现申请获取互斥对象所有权,原型如下:
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
该函数有两个参数,含义如下:
hHandle:所请求的对象的句柄,该对象可以是针对于互斥对象,也可以是其他类型的对象。本文中针对的是互斥对象。一旦所请求的互斥对象处于有信号状态那么函数就会立刻返回。如果请求的互斥对象始终处于无信号状态,则该函数就会一直等待,暂停该线程的运行。
dwMilliseconds:等待的指定的时间间隔,以毫秒为单位,两个极端就是0和INFINITE,如果是0,那么该函数将会立刻返回测试互斥对象的状态并且立即返回;如果是INFINITE就会就会一直等待直到等待的互斥对象处于有信号的状态。如果是个非零数值的话,WaitingForSingleObject函数时间到了就不得不返回了。
总之,有两个返回条件(一)有信号(二)时间到
说了那么多,这个函数的可能返回值如下:
1.WAIT_OBJECT-0:所请求的对象不被占用,有信号
2.WAIT_TIMEOUT:时间间隔已过并且无信号
3.WAIT_ABANDONED:所请求的对象是一个互斥对象,并且先前拥有该对象的线程在终止前还没有释放该对象。这时候,对象的所有权将授予当前调用线程,并且失去信号。
3.互斥对象的释放:
线程拥有互斥对象的时候可以对共享资源进行访问,访问结束后,应该释放互斥对象的所有权,需要调用ReleaseMutex函数:
原型:
BOOL ReleaseMutex(HANDLE hMutex);
这个函数只有一个HANDLE类的参数,即需要释放的互斥对象的句柄。该函数的返回值是BOOL型,调用成功则返回非零值,否则返回0.
在下一篇水文中,我们就把最终版本的买火车票写出来,各位兄贵可以看看实际是怎么用的。