关于多线程同步的一点总结

有些话、适合烂在心里 提交于 2020-02-18 11:26:39

这两天看了下 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.

 

 

大神的东西就是好,虽然有缺漏,但是让人受益匪浅啊。上面的总结要是有错漏,希望看客使劲揭。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!