为什么说GUI是单线程化的

刚好最近实现了一版事件模型,GUI 的逻辑处理几乎都由事件驱动,我认为比较重要的原因有:
事件模型就是典型的"职责链模式"(Chain-of-responsibility pattern),看看职责链的优势就知道了:可动态增加减少接收者,可动态调整接收优先级
每个接收对象都有机会响应事件,每个事件可由多个对象同时处理
对于处理不了的事件,接收对象可以不做处理,减少外部耦合
对于已经处理的事件,接收对象可以选择停止派发,也可以选择继续派发
事件模型还充分应用了"监听器模式":解耦事件发送者和接收者
每个事件可触发多种逻辑
还有很重要一点:单线程的应用如果想处理外部事件,都离不开消息循环,而事件模型和消息循环是天生一对。桌面上,最广为人知的消息循环恐怕就是Windows了,WinMain 方法都是一个死循环,不断的读取并处理Windows消息,大家都玩过你懂的。(派发给窗体)
网页上,JavaScript 应用也是单线程的,靠浏览器的消息循环驱动各种事件和回调。(派发给DOM)



作者:Jare Guo
链接:http://www.zhihu.com/question/26805116/answer/34124946
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



 现代的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中的对象,包括可视组件和数据模型,都只是被事件线程访问。当然,这只把线程安全负担的一部分推给了应用程序的开发者,他们必须确保这些对象是被正确限制的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值