一. 一般等待
1. sleep()
在操作系统中止此线程动作,直到渡过某个时间之后才恢复。
- VOID Sleep(
- DWORD dwMilliseconds // sleep time
- );
VOID Sleep(
DWORD dwMilliseconds // sleep time
);
实际上你不可能事先知道什么事情要等待多久,比如一个高优先级线程抢占执行的话,这个时间将变得不可预测。
要注意的是,Sleep( ),会放弃系统分配的剩余的时间片,这样 OS 就能更好的服务其他的进程和线程了。
2. busy loop
- for (;;)
- {
- GetExitCodeThread(hThrd1, &exitCode1);
- if ( exitCode1 == STILL_ACTIVE )
- puts("Thread 1 is still running!");
- }
for (;;)
{
GetExitCodeThread(hThrd1, &exitCode1);
if ( exitCode1 == STILL_ACTIVE )
puts("Thread 1 is still running!");
}
忙等,是很浪费CPU时间的!因为 for( ) 在一直工作。
二. 等待线程结束
- //等待一个线程结束
- DWORD WaitForSingleObject(
- HANDLE hHandle, // handle to object
- DWORD dwMilliseconds // 最长的等待时间,INFINITE 表示无穷等待
- );
- // 返回值:
- // WAIT_FAILED, 表示函数失败
- // WAIT_OBJECT_0, 表示等待的核心对象变成激发状态
- // WAIT_TIMEOUT, 表示核心对象在变成激发状态之前,时间终了了
- //等待多个线程结束
- DWORD WaitForMultipleObjects(
- DWORD nCount, // handles 数组元素个数
- CONST HANDLE *lpHandles, // handles 数组
- BOOL bWaitAll, // TRUE 表示所有的handles都必须激发,此函数才得以返回
- DWORD dwMilliseconds // 终了时间
- );
- // 返回值:
- // WAIT_TIMEOUT, 时间终了
- // WAIT_FAILED, 表示函数失败
- // bWaitAA == TRUE, 返回值是 WAIT_OBJECT_0
- // bWaitAA == FASLE, 返回值减去 WAIT_OBJECT_0,就表示数组中的哪一个 handle 被激发了
- // WAIT_TIMEOUT, 表示核心对象在变成激发状态之前,时间终了了
//等待一个线程结束
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // 最长的等待时间,INFINITE 表示无穷等待
);
// 返回值:
// WAIT_FAILED, 表示函数失败
// WAIT_OBJECT_0, 表示等待的核心对象变成激发状态
// WAIT_TIMEOUT, 表示核心对象在变成激发状态之前,时间终了了
//等待多个线程结束
DWORD WaitForMultipleObjects(
DWORD nCount, // handles 数组元素个数
CONST HANDLE *lpHandles, // handles 数组
BOOL bWaitAll, // TRUE 表示所有的handles都必须激发,此函数才得以返回
DWORD dwMilliseconds // 终了时间
);
// 返回值:
// WAIT_TIMEOUT, 时间终了
// WAIT_FAILED, 表示函数失败
// bWaitAA == TRUE, 返回值是 WAIT_OBJECT_0
// bWaitAA == FASLE, 返回值减去 WAIT_OBJECT_0,就表示数组中的哪一个 handle 被激发了
// WAIT_TIMEOUT, 表示核心对象在变成激发状态之前,时间终了了
说明:
WaitForXXXObject( ),相当于一个新版的 sleep( ),它能够在某个线程结束时被调用。
WaitForXXXObject( ),像 sleep( )一样,只会占用很少的CPU,不会出现忙等现象,所以效率会高很多。
WaitForXXXObject( ),到底在等什么?其实它等待的是一些对象被激发。
三. 被激发对象
可被 WaitForXXXObject( )使用的核心对象有两种状态:激发与未激发,WaitForXXXObject( ) 在目标变成激发状态时才返回。
比如:
Thread 当线程结束时,线程对象即被激发
Process 当进程结束时,进程对象即被激发
Event 直接受控于 SetEvent(),PulseEvent(),ResetEvent()三个函数
Mutex 如果 mutex 没有被任何线程拥有,它就处于激发状态
Semaphore 当计数器内容大于0时,semaphore处于激发状态
当出现以上对象动作时,线程对象就会被激发,此时 WaitForXXXObject( ) 就能返回。
四. 示例代码
最多用三个线程来完成六项工作
- #define WIN32_LEAN_AND_MEAN
- #include <stdio.h>
- #include <stdlib.h>
- #include <windows.h>
- DWORD WINAPI ThreadFunc(LPVOID);
- #define THREAD_POOL_SIZE 3 //线程池大小为3
- #define MAX_THREAD_INDEX THREAD_POOL_SIZE-1
- #define NUM_TASKS 6 //共有6个任务
- int main()
- {
- HANDLE hThrds[THREAD_POOL_SIZE];
- int slot = 0;
- DWORD threadId;
- int i;
- DWORD rc;
- for (i=1; i<=NUM_TASKS; i++)
- {
- /* 当用完线程池里所有的线程时,要等待其它线程结束 */
- if (i > THREAD_POOL_SIZE)
- {
- /* 等待一个线程结束 */
- rc = WaitForMultipleObjects(
- THREAD_POOL_SIZE,
- hThrds,
- FALSE,
- INFINITE );
- slot = rc - WAIT_OBJECT_0;
- printf("Slot %d terminated\n", slot );
- CloseHandle(hThrds[slot]);
- }
- /* 创建 6 个线程 */
- hThrds[slot] = CreateThread(NULL,
- 0,
- ThreadFunc,
- (LPVOID)slot,
- 0,
- &threadId );
- printf("Launched thread #%d (slot %d)\n", i, slot);
- slot++;
- }
- /* 等待所有的线程结束 */
- rc = WaitForMultipleObjects(
- THREAD_POOL_SIZE,
- hThrds,
- TRUE,
- INFINITE );
- for (slot=0; slot<THREAD_POOL_SIZE; slot++)
- CloseHandle(hThrds[slot]);
- printf("All slots terminated\n");
- return EXIT_SUCCESS;
- }
- /*
- * This function just calls Sleep for
- * a random amount of time, thereby
- * simulating some task that takes time.
- *
- * The param "n" is the index into
- * the handle array, kept for informational
- * purposes.
- */
- DWORD WINAPI ThreadFunc(LPVOID n)
- {
- srand( GetTickCount() );
- Sleep((rand()%10)*800+500);
- printf("Slot %d idle\n", n);
- return ((DWORD)n);
- }
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
DWORD WINAPI ThreadFunc(LPVOID);
#define THREAD_POOL_SIZE 3 //线程池大小为3
#define MAX_THREAD_INDEX THREAD_POOL_SIZE-1
#define NUM_TASKS 6 //共有6个任务
int main()
{
HANDLE hThrds[THREAD_POOL_SIZE];
int slot = 0;
DWORD threadId;
int i;
DWORD rc;
for (i=1; i<=NUM_TASKS; i++)
{
/* 当用完线程池里所有的线程时,要等待其它线程结束 */
if (i > THREAD_POOL_SIZE)
{
/* 等待一个线程结束 */
rc = WaitForMultipleObjects(
THREAD_POOL_SIZE,
hThrds,
FALSE,
INFINITE );
slot = rc - WAIT_OBJECT_0;
printf("Slot %d terminated\n", slot );
CloseHandle(hThrds[slot]);
}
/* 创建 6 个线程 */
hThrds[slot] = CreateThread(NULL,
0,
ThreadFunc,
(LPVOID)slot,
0,
&threadId );
printf("Launched thread #%d (slot %d)\n", i, slot);
slot++;
}
/* 等待所有的线程结束 */
rc = WaitForMultipleObjects(
THREAD_POOL_SIZE,
hThrds,
TRUE,
INFINITE );
for (slot=0; slot<THREAD_POOL_SIZE; slot++)
CloseHandle(hThrds[slot]);
printf("All slots terminated\n");
return EXIT_SUCCESS;
}
/*
* This function just calls Sleep for
* a random amount of time, thereby
* simulating some task that takes time.
*
* The param "n" is the index into
* the handle array, kept for informational
* purposes.
*/
DWORD WINAPI ThreadFunc(LPVOID n)
{
srand( GetTickCount() );
Sleep((rand()%10)*800+500);
printf("Slot %d idle\n", n);
return ((DWORD)n);
}
说明:
代码是《Win32多线程程序设计》上的,很经典。
本文介绍了Windows环境下多线程程序设计中的线程等待机制,包括Sleep(), busyloop, WaitForSingleObject() 和 WaitForMultipleObjects() 的使用方法及示例代码。
360

被折叠的 条评论
为什么被折叠?



