1 回答
TA贡献1966条经验 获得超4个赞
现代的gui框架使用了一个略微不同的模型:模型创建了一个专门的线程,事件派发线程(event dispatch thread,RDT)来处理gui事件。单线程化的GUI框架并不仅仅存在于java中:Qt、NextStep、Macos Cocoa、XWindows,等等都是单线程化的。也并不缺少反面的尝试;有很多试图写出多线程的GUI框架的努力,最终都由于竞争条件和死锁导致的稳定性问题,又回到了单线程化的事件队列模型的老路上来:采用一个专门的线程从队列中抽取事件,并把它们转发给应用程序定义的事件处理器。(awt最初曾尝试在某种程度上支持多线程访问,单线程化地实现swing的决定主要基于AWT中的经验和教训。)多线程的GUI框架会尤其易受死锁的影响,部分原因在于,输入事件处理与任何GUI组件背后的对象模型之间存在偶发的交互。用户发起的动作总会冒泡似的从操作系统传递给应用程序—先是由os检测到一次鼠标点击,然后工具集把它转化为“鼠标点击”事件,最终它会作为一个高层事件(比如“buttonpressed”事件)转发给应用程序的监听器。另一方面,应用程序发起的动作又会以冒泡的形式传回操作系统—应用程序发起一个动作要改变某个组件的背景颜色,这会被转发给一个特定的组件类,最终转发给os进行渲染。两种动作以完全相反的顺序访问相同的GUI对象,需要保证让每一个对象都是线程安全的,这会导致一系列的锁顺序的不一致,这会直接引发死锁。这个问题机会在每一次GUI工具集的开发中都会出现,是经验之谈。模型—视图—控制器(mvc)模式的普遍流行形成了导致多线程GUI框架出现死锁的另一原因。把用户的互交分拨到模型、视图和控制器之间的写作中,极大地简化了GUI应用程序的实现,但这让不一致的锁顺序再次雪上加霜。控制器调用模型,模型通知视图已经发生了一些事情。控制器同样可以调用视图,视图可以依次回调模型来查询模型的状态。结果是,不一致的锁顺序再次伴随死锁的风险一同到来。Graham hamilton,sun公司的vp,在他的weblog中详尽地概括了这些挑战,描述了多线程GUI工具集之所以会成为计算机科学史上又一次“失败的梦”。如果多线程GUI工具集经过非常谨慎的设计;如果工具集能使它加锁的方法鲜明地显露;如果你非常聪明,非常仔细,并且对工具集的整体框架有着全局的把握,我相信你还是可以成功地编写出多线程的GUI来。但是如果这些事情有一些轻微的偏差,程序多数时候仍然运行良好,但是你会偶尔看到程序挂起或者运行故障。那些密切参与了工具集设计的人能够很好地运用这种多线程方案。不幸的是,我认为这些特性并没有和商业流行度成正比。一个中等能力的程序员,整日构建着被一些莫名其妙的原因困扰着而不能稳定运行的应用程序,我们很容易落入这种境界。于是应该程序的作者会倍感怨恨与失落,对无辜的工具集恶语相加。单线程化的GUI框架通过现场限制来达到现场安全性;所有GUI中的对象,包括可视组件和数据模型,都只是被事件线程访问。当然,这只把线程安全负担的一部分推给了应用程序的开发者,他们必须确保这些对象是被正确限制的。
- 1 回答
- 0 关注
- 680 浏览
添加回答
举报