可使用JDK提供的Exchager类进行同步交换:进行数据交换的双方将互相等待对方,直到双方的数据都准备完毕,才进行交换。Exchager类不多用到,但理解数据交换的时机却十分重要,这是一个基于trade-off的系统设计。下述分析方法能扩展到诸多系统设计的场景中,帮助咱们更好的进行trade-off。git
《Java并发编程实战》中介绍了断定数据交换时机的两种方案,却不甚清晰。从“时机选择的目的”出发,实际上存在着三种方案,各方案又有优劣,从而产生了trade-off。本文比较了这三种方案,经过对数据交换时机的分析增强trade-off的意识。github
数据交换:在Exchanger的两方栅栏机制中,双方互相等待对方的数据。编程
如读线程在读取发生前持有“空缓存”,写线程在写入完成后持有“满缓冲”(“满”只表示写入完成),那么数据交换就是指将读线程的“空缓冲”与写线程的“满缓冲”交换。缓存
依据“时机选择的的目的”,存在三种方案:并发
从交换次数最少的目的出发,交换行为应该发生在缓冲满和缓冲空时,这两种状况下都不得不发生交换,以知足最低的响应需求。性能
缓冲满时(填充线程的缓冲),填充任务发现没法继续填充缓冲区,就发起交换,以减小数据(到空)继续填充;缓冲空时(清空线程的缓冲),清空任务发现没法继续清空,就发起交换,以增长数据(到满)继续清空。线程
也能够将实际的交换任务委派给专门的交换线程,填充任务和清空任务都向该线程申请执行交换。设计
从响应最及时的目的出发,交换行为应该发生在缓冲刚增长数据和缓冲刚减小数据时,以知足“存在数据即交换”的最高的响应需求。get
这种方案至关于去掉了缓冲区。一方面,一旦缓存不空就马上发生交换,交换后就没有了数据;另外一方面,一旦缓存空就开始交换数据,交换后缓存就不空。看起来数据根本须要写入缓存就完成了交换。同步
也能够设置一个特别小的缓冲,好比1个字节。但交换区的缓冲减少,只会让交换双方各自维护的缓冲区加大。
很明显:交换次数最少的话,一些数据的处理过程就将延迟;响应最及时的话,交换频率过高,很浪费性能,甚至大型系统中耗电都会成为问题。
因此可采用折中的方案,达到适度的交换频率和响应:交换行为发生在缓冲被填充到必定程度并保持必定时间 t 后,同时一旦缓冲满或缓冲空就当即发生交换。
若是将时间 t 设置为 0,则退化为方案2;若是将时间 t 设置无穷大,则退化为方案1,从而既能兼容以上两种方案,又能根据实际响应需求静态配置,甚至根据实时的性能分析结果进行动态调整。
若是将Exchager比做“数据交换系统”,方案3即完成了对“数据交换系统”的trade-off,也就是基于成本(如耗电等)、收益(如延迟等)对系统设计做出的权衡、妥协。
经过对三种Exchager数据交换时机的分析,增强了咱们在系统设计中的trade-off意识。
《Java并发编程实战》中介绍了方案1和方案3。直接在书中看到方案1和方案3可能很难理解,但分析了上述trade-off过程后,就能轻松理解数据交换的时机了。
本文连接:从Exchager数据交换到基于trade-off的系统设计
做者:猴子007
出处:https://monkeysayhi.github.io
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布,欢迎转载,演绎或用于商业目的,可是必须保留本文的署名及连接。