PB多线程的缺陷与实现机制浅析

来源:互联网 发布:may it be 编辑:程序博客网 时间:2024/06/05 03:15
      昨天提到了PB多线程的问题,我其实一直都想写一个PB通用线程库,但一直没有找到好的方法去实现,主要的原因有几点。PB的多线程功能很少有人去深入分析过其实现机制,也没有在这方面的文档可以参考,以前我写过一篇PB的线程使用的心得,也没有完全回答出所有的疑问,今天我想解决一下这个问题。
      为什么PB中使用线程功能时可能会出现程序假死的情况(死锁)?要回答这个最主要的问题还是回到刚才提到的线程库的设想中来解决。
      线程库首先不能使用PBNI去实现,因为在PBNI里你没有办法与PB同步对象的状态,这可能随时会发生资源竞态的问题,所以必须使用PB内置的线程功能[SharedObject族函数],这样就引出了上面要回答的问题。
      首先说说使用PB自带线程功能的好处(PB多线程功能是真多线程,有人说是用timer模拟的,这。。。。),你可以像单线程一样去使用任何代码,任何函数(包括创建不可视对象、可视对、事务等),你只要像单线程一样去使用它们就绝对不会有问题,但如果你要像使用多线程一样去使用它们那我们就来谈谈PB线程的一些限制(也可以是缺陷吧)。
      多线程的一个最基本要解决的问题就是如何在线程间通讯,有很多种手段,都是为了对同一数据进行有序访问的控制手段。在PB的多线程环境中线程间的全局变量是相互独立的(隔离),所以你如果想在线程间通讯PB只提供了通过不可视对象做为桥梁,当你试图直接在线程间操作可视对象时程序会立即crash,这没什么不对本来就不应该这样做。
      为什么不可视对象就可以?这相当具有迷惑性,你会看到在PB的多线程环境中线程间通过不可视对象互操作时没有任何状态同步的代码来控制这种访问顺序,为什么不会出现资源竞态的问题?原因就是PB内建的消息队列为不可视对象实现了自己的同步机制,当你同步调用线程间不可视对象的函数时其实也是一个post,    如:in_Callback.of_GetThrState()实际调用的(伪代码)就是in_Callback.Post of_GetThrState(),这个post是PB自己加上的并且比用户代码下的post优先级高,这个机制就像Win32 API SendMessage在多线程通讯时的处理手段。如果in_Callback所在线程当前有函数正在运行那么你的调用线程将会一直等待对方执行完当前函数后检查PB消息队列然后再执行你调用的函数,最后调用线程恢复执行,但并不总是成功的,in_Callback所在线程如果执行时间过久的话调用线程可能会一直等待,这样程序就出现了假死(死锁),因为PB可能不会再去检查消息队列并让调用方返回(之所以说可能是因为我觉得这是PB的BUG),在线程执行函数内加yield()的话可以在一定程度上缓解这个问题,但如果有IO之类耗时操作的话你仍然无法完全避免这个问题。
      刚才提到了“in_Callback所在线程”,在PB中每一个对象的创建都会与创建代码所在线程绑定在一起,这可能是为了实现同步机制吧,但这刚好成了PB线程最大的缺陷,这让你只能使用PB内建的同步机制进行线程通讯,在线程任务分配时你不得不经常来回拷贝数据这种费时费空间的做法,同时还要避免上面提到的超时不返回造成假死的缺陷。
      以上就是PB多线程老受人诟病的原因和我分析出来的原理,我一直没找到好的方法去实现一个通用的线程库的原因就是没办法完全隐藏上面的这些细节,那会制约对库的使用。
0 0
原创粉丝点击