这两天看了下 MoreWindows 《秒杀多线程》系列的博客,稍微总结一下,就当笔记了。
http://blog.csdn.net/column/details/killthreadseries.html
1. CreateThread()与_beginthreadex()的区别
_beginthreadex在创建线程前(即调用CreateThread()前),先申请了一个用于存放线程私有数据的
_tidata 类型成员.
2. Interlocked系列函数
* LONG __cdecl InterlockedIncrement(LONG volatile* Addend); 相当++Addend;
* LONG __cdecl InterlockedDecrement(LONG volatile* Addend); --Addend;
* LONG __cdecl InterlockedExchangeAdd(LONG volatile* Addend, LONG Value); Addend + Value; 减法即Value取负值
* MSDN上对WaitForMultipleObjects()函数第一个参数作了说明:The maximum number of object handles is MAXIMUM_WAIT_OBJECTS(64)。
3. 多线程同步 CriticalSection 临界区法
初始化函数:void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
销毁函数:void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
进入临界区函数:void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
离开临界区函数:void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
要点:一旦有线程进入临界值,则临界区归线程所有,可以多次进出
概念一:主线程与子线程传递数据同步(所谓同步),假如用简单临界区法限制子线程的创建顺序是不行的,因为临界区归主线程所有,它可以随意进出,所以相当于没有设置临界值。想要通过临界区法来进行主子线程同步其实也是可以的,但是必须是通过控制主线程进入临界区的次数,如:只允许进入一次。
概念二:子线程不相互影响(所谓互斥),由于非相同线程,显而易见可以使用临界区来进行互斥。
旋转锁轮询概念:在将等待线程挂起前,操作系统会先轮询(即不断循环),之后再挂起。因为挂起等待比较消耗资源。(单核忽略旋转锁)
初始化临界区并设置旋转次数函数:BOOLInitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection,DWORD dwSpinCount); //旋转次数一般设置为4000。
修改临界区的旋转次数函数:DWORDSetCriticalSectionSpinCount(LPCRITICAL_SECTION lpCriticalSection,DWORD dwSpinCount);
4. 线程同步 事件法
事件声明:因为事件Event其实也是一个内核对象,所以类型Handle.
创建事件函数:HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, //自/手动重置事件
BOOL bInitialState,
LPCTSTR lpName
);
获得一个事件句柄函数:HANDLE OpenEvent(
DWORD dwDesiredAccess, //一般EVENT_ALL_ACCESS
BOOL bInheritHandle, //一般True
LPCTSTR lpName //名称
);
触发事件函数:BOOLSetEvent(HANDLE hEvent);
重置成未出发事件函数:BOOL ResetEvent(HANDLE hEvent);
事件销毁:CloseHandle()
事件脉冲:BOOL PulseEvent(HANDLE hEvent);//脉冲:一开一关,如果手动事件则所有手动等待事件执行后,函数关,如果自动事件则一个事件执行并自动关。
5. 多线程同步 互斥量法
Mutex也是一个内核对象,类似与临界区,但是互斥量可以用于进程间同步,个人觉得这和它是一个内核对象有关。
互斥量创建函数: HANDLECreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName //名字,互斥量的标志,多进程间通信
);
互斥量打开函数:HANDLEOpenMutex(
DWORD dwDesiredAccess,//一般MUTEX_ALL_ACCESS
BOOL bInheritHandle, //一般TRUE
LPCTSTR lpName //名称
);
互斥量触发函数:BOOL ReleaseMutex (HANDLE hMutex);
互斥量清理即内核对象清理:CloseHandle()
6.多线程同步 信号量法
Semaphore也是一个内核对象。个人再次觉得因此它可以用于不同进程间通信。
信号量创建:HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName //名字,信号量标识
);
信号量打开(个人觉得打开类似于将信号量暴露在当前进程下):
HANDLE OpenSemaphore( DWORD dwDesiredAccess, //一般SEMAPHORE_ALL_ACCESS
BOOL bInheritHandle,
LPCTSTR lpName );
释放信号量(递增信号量的当前资源计数):
BOOL ReleaseSemaphore( HANDLE hSemaphore,
LONG lReleaseCount, //释放资源数目
LPLONG lpPreviousCount //获取当前资源数目 );
关闭(因为是内核对象,所以依旧是下面函数):
CloseHandle()
注:这里没有信号量的递减(占用)函数,我个人觉得应该是在 WaitForMultipleObjects();等待到正值的信号量时,继续运行并做递减操作。
MSDN中查到:Each time one of the wait functions returns because the state of a semaphore was set to signaled, the count of the semaphore is decreased by one.
大神的东西就是好,虽然有缺漏,但是让人受益匪浅啊。上面的总结要是有错漏,希望看客使劲揭。
来源:https://www.cnblogs.com/DoubleZ/p/3231635.html