在VC中编写程雪,调用API函数CreateThread()创建线程。
该函数原型如下:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
该函数的作用是用于创建一个线程,并将返回该线程的句柄。其中,各个参数含义如下:
dwCreationFlags取值 | 作用 |
CREATE_SUSPENDED | 线程创建成功后暂停运行 |
0 |
线程创建成功后立即运行
|
使用API函数操作临界区步骤
(1)定义临界区对象
CRITICAL_SECTION m_sec;
(2)初始化临界区对象
InitialzeCritivcalSection(&m_sec);
(3)线程进入临界区并拥有临界区对象的所有权
EnterCriticalSection(&m_sec));
(4)线程释放临界区的所有权并离开临界区
LeaveCriticalSection(&m_sec);
(5)用户调用DeleteCriticalSection(&m_sec)函数将该临界区从内存中删除
事件对象是指用户在程序中使用内核对象的有无信号状态实现线程的同步。
使用函数CreateEvent()创建事件对象并返回事件对象
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
如果该函数调用成功,则返回新创建的事件对象。其参数及意义如下:
参数lpEventAttributes是结构体SECURITY_ATTRIBUTES的指针,表示新创建的事件对象的安全属性。如果该参数为NULL,则表示程序使用的是默认安全属性。
参数bManualReset表示所创建的事件对象是人工重置还是自动重置。如果该参数为true,则表示程序所创建的事件对象为人工重置对象。如果为false,则表示创建的事件对象为自动重置对象。
参数bInitialState表示事件对象的初始状态。如果该参数为true,则表示该事件对象初始时为有信号状态。否则,表示事件对象初始化时为无信号状态。
参数lpName表示事件对象的名称。如果该参数为NULL,则表示程序创建的是一个匿名的事件对象。
注意:如果参数bManualReset设置为true,则表示当调用线程获得其所有权后,用户需要显式地调用函数ResetEvent()将事件对象设置为无信号状态。如果为自动重置的事件对象,则系统会自动将其设置为无信号状态。所以,一般情况下用户编程均将事件对象设置为自动重置。
例如,用户创建一个初始化状态为有信号并且是自动重置的事件对象。代码如下:
HANDLE hevent;
//定义事件对象
Hevent=::CreateEvent(NULL,false,true,NULL);
//创建事件对象
...
//省略部分代码
当用户创建事件对象时,如果将其初始状态设置为无信号,则需要用户手动将其设置为有信号状态。实现该功能可以调用函数SetEvent()将指定的事件对象设置为有信号状态。该函数原型如下:
BOOL SetEvent(HANDLE hEvent);
该函数调用成功,则返回true。否则,将返回false。
当然,线程也可以通过调用函数WaitForSingleObject()主动请求事件对象。该函数原型如下:
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
该函数将在用户指定的事件对象上等待。如果事件对象处于有信号状态,函数将返回。否则,函数将一直等待,直到用户所指定的时间到达。各参数及其意义如下:
参数hHandle表示函数所等待的事件对象句柄。
参数dwMilliseconds表示该函数将在事件对象上的等待时间,如果该参数为INFINITE,则该函数将永远等待。
互斥对象与前面所学的临界区对象那个和事件对象的作用一样,均用于实现线程同步。但是,互斥对象还可以在进程之间使用。在互斥对象中,包含一个线程ID和一个计数器。线程ID表示拥有该互斥对象的线程,计数器用于表示该互斥对象被同一线程所拥有的次数。
用户可以调用API函数CreateMutex()创建并返回互斥对象。该函数原型如下:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
如果该函数调用成功,将返回新创建的互斥对象句柄。否则,将返回NULL。各参数及其意义如下:
参数lpMutexAttributes指定新创建互斥对象的安全属性。如果该参数为NULL,表示互斥对象拥有默认的安全属性。
参数bInitialOwner表示该互斥对象的拥有者。如果为true,则表示创建该互斥对象的线程拥有其所有权。如果为false,表示创建互斥对象的线程不能拥有该互斥对象的所有权。
参数lpName表示互斥对象的名称。若该参数为NULL,则表示程序创建的是匿名对象。如果用户为该参数指定值,则在程序中可以调用函数OpenMutex()打开一个命名的互斥对象。
例如,用户创建一个匿名的互斥对象,代码如下:
HANDLE hmutex;
//声明互斥对象句柄
hmutex=::CreateMutex(NULL,FALSE,NULL):
//创建互斥对象并返回其句柄
...
//省略部分代码
线程使用完该互斥对象以后,用户应该调用函数ReleaseMutex()释放对该互斥对象的所有权,也就是让互斥对象处于有信号状态。函数ReleaseMutex()的原型如下:
BOOL ReleaseMutex(HANDLE hMutex);
如果该函数调用成功,则返回true。否则,将返回false。参数hMutex表示将释放的互斥对象句柄。
例如,用户将上面创建的互斥对象句柄hmutex与调用该句柄的线程进行分离。代码如下:
...
//省略部分代码
::ReleaseMutex(hmutex);
//释放互斥对象句柄
在互斥对象中,线程也可以调用函数WaitForSingleObject()对该对象进行请求。当互斥对象无信号时,该函数将一直等待,直到该互斥对象有信号或用户所指定的等待时间已过。否则,该函数将返回。
3.2