多线程开发是软件开发的一个难点,下面说一说我多年的开发体会:

数据保护:

如果一个资源(一般是一组相关数据)如果可能“同时”被多个线程访问,为了保证数据的“一致性”,我们应该对该资源进行保护。

一般是使用一个同步对象来保证没有多个线程同时对该资源“同时访问”,以Windows为例,常用的同步对象有CriticalSection、Mutex等待,CriticalSection只能够用于同一个进程中的线程间同步,而Mutex可以用于不同进程之间,我们一般吧获得一个同步对象称为对一个资源加锁,反之称为解锁。

一个线程要想读写需要保护的资源,先要对该资源加锁,读写完毕后必须解锁。

一般对资源的操作时原子的,那就不会破坏数据的完整性,一般不用保护,如多个线程可以对一个DWORD的值进行读写,不会有问题。

为了提高程序的性能,如果多个线程仅仅同时读一个资源,可以不加保护,但是只要有一个线程在修改保护资源,其他线程对该保护资源也就不能读也不能写了。


关于死锁:

多线程编程的一个难点不是仅仅对资源保护这么简单,一个头痛的问题是如果规划不好,会导致多个线程死锁,比如:线程1在占有一个同步对象A时,企图获取线程2已经占有的一个同步对象B,而线程2而此刻也在企图获取同步对象A,这样线程1和线程2就进入了一种称作“死锁”的状态,谁也不能往下走了。

显然产生死锁是有条件的,1锁嵌套,2是不同线程加锁顺序不同。保证所有线程按照同一个顺序获取同步对象似乎就能解决死锁的问题了,然而在实际开发中,做到这一点是很难的,而且死锁并不是仅仅相互等待被对方占有的一把锁这么简单。

死锁有时候会很“隐蔽”,考虑这样一种情况:工作线程在没有释放锁A时,调用“SetWindowText”修改主线程的一个窗口的标题,而主线程此刻正试图获取被工作线程占有的A锁,会怎么样呢?显然主线程在没有得到A锁时,是动不了的,而工作线程呢?工作线程给主线程Send了一个消息,在主线程没有反馈前,是不会往下走的,而此刻主线程也不会处理工作线程Send过来的消息,这样他们就死锁了。

解决消息死锁的方法是:主线程使用MsgWaitForMultiObjects来获取锁,该API可以在等待的锁被释放或者有其他线程Send消息时返回,就可以做到边等边看,在等待锁的同时处理消息。

死锁的情况远不止上面说的,其实不但消息和同步对象之间可以锁死,而且消息之间也可能发生死锁,还可能多个线程循环等死。仔细研究一下InSendMessage和ReplyMessage的使用场合你会发现还有你没想到的死锁方法,呵呵!

死锁的检测手段:
如果你已经发布的程序在客户那里处了问题,如何确定是否是死锁了?是哪几个线程出了问题?在哪里发生了死锁呢?
。。。
如果有好心人给一个邀请码,就继续往下说,如果没有就算了,呵呵!