Windows多线程技术研究(三):线程API
介绍完线程的基本概念后,接下来描述在windows下如何创建线程,以及相应的使用多线程一些基本API。
使用CreateThread()函数来创建一个线程。其函数原型为:
HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpThreadAttribules,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParamenter,
DWORD dwCreationFlags,
LPDWORD lpThreadid
) ;
lpThreadAttribules – 新线程的serurity属性。NULL表示使用缺省值。
dwStackSize – 新线程堆栈的大小。0表示缺省大小:1MB。
lpStartAddress – 新线程开始地址。是一个函数指针,可以传入一个函数名。
lpParamenter – 新线程函数的参数。
dwCreationFlags – 创建标志。默认为立即执行。
lpThreadid – 新线程的ID。
CreateThread()传回来的handle被称为一个核心对象。当完成线程工作后,需要调用CloseHandle()函数来释放该核心对象。
Threads的行为很像中国人,如果让他们单兵作战,那么性能很好,效率也不错;但是一旦让他们合作,那各种麻烦、bug就会纷纷而至。所以你必须在使用时多加考虑。
由于当有多个线程执行时,这些线程在某一时刻谁执行都是不确定的。所以如果多个线程之间没有访问共享资源,并且不需要考虑所有线程都执行完或者某几个线程执行完时,那么多线程就变得很简单,创建完多个线程后放任其执行即可。但是一旦要访问共享资源或者需要等待多个线程执行完时,则需要一些其他处理。
互斥:
互斥是由于多个线程需要访问同一资源造成的,最简单的方法是临界区。设置一个CRITICAL_SECTION类型的变量,使用InitializeCriticalSection()来初始化该变量,然后在线程访问共享资源之前,使用EnterCriticalSection()来设置临界区,访问完之后再使用LeaveCriticalSection()来取消临界区。最后线程结束后调用DestroyCriticalSection()来删除该临界区变量。
等待:
很多情况下,需要让多个线程都执行完或者部分执行完后再做其他操作。使用WaitForSingleObject()和WaitForMultipleObjects()函数来进行等待。
DWORD WaitForSingleObject(
HANDLE hHandle, //线程句柄
DWORD dwMilliseconds //等待时间,INFINITE为等到线程结束
);
DWORD WaitForMultipleObjects(
DWORD nCount, //lpHandles指向的句柄个数
CONST HANDLE * lpHandles, //线程句柄数组
BOOL bWaitAll, //true等待句柄数组中的所有线程,false
//等待其中一个线程执行完
DWORD dwMilliseconds //等待时间,INFINITE为无限等待直至
//一个线程结束或所有线程结束
);