windows 多线程编程的几点经验 (防止死锁)

来源:互联网 发布:淘宝车牌选号 编辑:程序博客网 时间:2024/05/16 18:25

转自:http://www.cnblogs.com/kex1n/archive/2011/08/05/2128335.html

关于防止死锁方面的介绍比较少,但前5点经验肯定都是作者的心得和经验总结,因为我也遇到过,但还没有进行总结。

1) 不要在线程函数体内操作MFC控件,不要再线程里面调用UpdateData函数更新用户界面,而应该尽量采用发送消息的方式,在主线程的消息响应函数中操作控件;

2)不建议采用SendMessage往主线程发送消息,因为它是同步的,阻塞的,可以考虑采用PostMessage代替;

3)线程退出时,尽量不要使用TerminateThread函数,而尽可能的让线程自己退出;

4) 当线程退出时,必须先等待工作者线程退出,主线程才退出,但是在主线程里面不要使用WaitForSingleObject或WaitForMultiObjects等待线程结束,因为它可能造成死锁,当主线程使用这两个函数时,主线程就挂起了,尤其在第 (1), (2) 种情况下,工作者线程还在调用主线程里面的资源,这样造成死锁;

5) 为了防止退出死锁的发生,尽量使用MsgWaitForMultipleObjects函数,因为该函数等待时,可以等待线程句柄 有信号,而且还可以等待消息,不会造成死锁;

1. 原子访问:(从来不会把线程切换到等待状态)
InterlockedExchangeAadd; // 原子加减
InterlockedIncrement;
InterlockedExchange; // 原子赋值 应用:旋转锁(少用)
InterlockedExchangePointer;

2. 高速缓存行:
CPU会将所要取的内存数据的临近数据存到高速缓存行,因此将只读和可读写的数据适当分开组织可提高性能。
指针永远不需要volatile关键字修饰,因为会永远读取内存地址,编译器不会做任何优化。

3. 高级同步
关键段(critical section):锁代码(只能在同一个进程中同步,无法指定最长等待时间,容易死锁)
如果有全局CRITICAL_SECTION对象,则可以用它锁不同的代码段;
EnterCriticalSection和LeaveCriticalSection;
必须初始化和反初始化:IntializeCriticalSection和DeleteCriticalSection;
优点:内部使用Interlock函数,速度快;
缺点:无法用来在多个进程之间对进程进行同步;

多处理器调用没有问题,只有一个处理器的线程能执行,其余都要等待;
由于线程进入等待状态要被系统从用户态切换到内核态,因此在使用关键段是应该总是同时使用旋转锁:
IntializeCriticalSectionAndSpinCount,旋转锁循环次数经典值是4000;
Slim读/写锁

以上方法的线程同步将保证线程在用户态:速度快。


原创粉丝点击