《并发哲学:从编程入道到开悟升天》4.4 谈为人处世与职场素质
谈为人处世与职场素质
本节我们探讨一个有意思的话题,正如先前所说,Golang通过高级的顶层抽象,帮助我们止部抽象链,不用像其他编程语言一样,考虑许多底层的问题。这样做的一大好处就是,我们能够借助Golang,在并发编程过程中更加直观的对任务目标以及实现过程进行直接编码。
在4.2节中,我们通过构建“李华的早晨”,通过对李华经历的早晨种种事情的抽象和梳理,发现最终只需要进行对原先第三章内学习的代码块、范式拼接即可,真正做到了90%的时间考虑如何编码,10%的时间书写代码,如此这般“高级程序员”的风范。
本书写到这里,我们不禁要思考一个问题,借助代码究竟可以做到多直接的抽象,而这些实际抽象出来的问题,映射在现实生活的模型,又蕴含着怎样的哲理?本节,我们简要探讨由并发编程引出的基本世界观和具象的为人处世以及职场的素质。
不要在没有成果的问题上有过多浪费
我们在3.3节中,介绍了Golang编译过程中会对代码加入运行时检查,这有助于避免运行过程中由协程带来的的死锁等问题。我们认为这是Golang对世人的警醒:不要在没有成果的问题上有过多浪费。
什么叫没有成果?总的来看,这体现在两点:
- 已经面临彻底的资源枯竭,从根源上来说,不再有产生成果的可能
- 即使还有资源,但由于不恰当的协调,现有的组织无法基于这些资源再有其他的成果了
对于第一点,我们比较容易理解。俗话说,巧妇难为无米之炊,如果已经在关键资源上枯竭,那么再好的领导也无法带领手下(甚至手下本身的人都已经没了)进一步的产出成果。在这种困局下,不如早早放弃方为王道。
而对于第二点,往往是许多人纠结的地方:我们还有资源啊!有资源,就有希望,人在资源在,只要时间够长,还怕拖不出来成果不成?
代码会说话,通过4.1内关于锁的介绍我们明白,抛开死锁不谈,即便大家都还在忙活,但也有可能陷入活锁的地步。只要是锁住,结局总会迎来暗淡。活锁都如此,更何况死锁。
因而,程序会在发现deadlock后强制终止程序的执行,也希望大家能够明白,如果现有的条件通过理性的分析,不再具有产生成果的可能,也就不要在相关的问题上有过多的时间浪费了。
明确职责边界解决冲突
并发解决的是顺序任务之间协调分配的问题。从第一章我们了解到,考古学家创新地认为,投掷能力的进化是人类进化的一大里程碑,随之带来的,是协作水平的全面提升。
而在日常生活的协作中,我们不免要面对很多冲突。这些冲突往往都是因为资源导致。不同的国家因为土地资源而发动战争,邻里因为占地问题破口开骂,甲乙丙丁为了小芳一个女人可以大打出手,这些都是因为资源分配不均匀,或者是没有按照各自的意图分配,而产生的冲突。
但在完全由包工头控制的体系内,也就是我们自己分配任务的问题上,如果有多人同时完成一件事情,同样需要明确资源边界。
资源边界可以是相对的,具体体现在“没有东西过来,你别动”“有锁,你别动”,通过相对条件,来明确当前资源的归属,“没有东西过来”这在流水线等场景下十分常见,而“有锁”则更是体现在生活的方方面面。有锁的厕所门你别硬开,有锁的自行车你别弄走,诸如此类,等等。
而还有一种则是不借助任何工具和相对条件的,通过直接管理和事前划分,约定职责边界。
通过代码可知,事先约定这种方式是最为简单粗暴,不需要依赖其他的工具,但却呆板并损失了可扩展性。虽然在制度和工具出现前,人们可以通过事先约定来临时实现职责边界划分,但总的说来,建立完善制度,加强管理,形成有力领导,划定好不同任务安排之间的资源边界,能够有效解决团队内冲突。
打扫干净自己的东西不惹人嫌
正如在编程中各种泄露(内存泄露也好,还是Golang特有的goroutines泄露也好)惹人烦一样,生活中也同样。
自己在开展许多工作当中,需要临时申请很多资源,也需要创建很多临时的结构等,这些资源和结构往往和其他人没有关系,仅仅是为了自己工作方便开展而产生。这种情况下,一定要确保事情完毕后,由自己产生的东西严格清理,才不会惹人嫌。
将临时作用域完全自己可控,就做到了闭包。在3.5节Golang并发范式中,我们了解到协程闭包被大量使用,用于构建可控安全域。
善于处理“并发”的领导是好领导
这个问题答案很显然是多样的,但我们通过对于并发设计中涉及的考量,可以对日常生活中团队的好领导有一个定义。简要来说,我们认为下面的特质应该是好领导具备的:
- 能够清晰的划分任务边界,合理有序的安排任务
- 能够安排内聚性强的任务给一个人,发挥单人优势,提升任务处理效率
- 在合适的场景下,控制合适的团队规模,以解决问题为导向,弹性伸缩解决相仿问题的人力
- 对于发配的任务,进行适当的监测,能够根据任务的行进状态,做出合理调整
- 建立良好的制度,能够对暂时解决不了的问题进行兜底,确保项目正常运转
- 能够建立良好的激励机制,提升需要效率任务的执行效率
也许特质还需要很多,但依托对优秀并发程序的分析,我们可以渐渐相仿的得出更多好领导应该具有的特质。
重要的事情认真做,简单的事情重复做
在3.6节可伸缩并发设计中,我们探讨了针对系统中重要的协程,需要建立监测机制,包括心跳等手段,并有完整的定损止损流程,确保在重要协程被停止后,可以及时的拉起。
而同样在3.6,也在4.3内提及的网络编程例子,对于用户海量的请求,来一个请求就发配一个协程去做,这样的协程即便因为意外出现问题,也是可以容忍的。Golang提倡用海量协程压制化作业抵消低价值协程关停风险。
映射在生活中,不难发现,生活中有很多需要小心维护,价值重要的事情,我们对这些事情需要建立较为完善的价值评估体系,并根据推进情况调整方向,在遭遇问题时投入一定精力解决。而对于较为简单的事情,诸如玩英雄联盟等游戏的时候点击鼠标,我们会确保在战场上鼠标移动到需要的地方就开始频繁点击,即便先前一次点击有错误,这种错误很快会因为之后正确的点击而抵消掉。
掌握合理的效率优化
人们天生就对擅长处理“并发”,也就是任务协调的人们羡慕和赞许。看看街边的小丑等艺人,拿出三个球在天空中轮换投掷,对大部分人来说这称之为绝活。
但是,这并不意味着人们需要事无巨细的考虑和优化生活中的种种细节,把每一个可以进入“并发”状态的事情都开启一个“并发任务”。正如在4.1节中我们看到,计算机编程史上的大佬们,都对并发技术研究的推进格外谨慎,甚至到了胆怯的地步,这就是因为任务分配和切换的粒度越细、越频繁,除非有一个Golang这种自带优化的管家,否则,资源竞争、各种锁的问题就会接踵而至。
相信很多人都遭遇过自己把一天的事情安排的满满当当,各项工作同时发配力图更多的并行发展,最后一旦失控所有的事情变得一团糟。
在自己的节奏内,事情一件一件的串行去做未尝不是好事。根据自己的能力范围,掌握合理的效率优化,有时候能取得更大的价值。
有些事情适合烂在肚子里
3.2内龟兔赛跑的例子,乌龟输了,在select语句后面,乌龟有一句战败感言。这样的程序可以通过编译,但早在语法检查阶段,细心的你可能会发现,诸如Goland等IDE会标记出这句战败感言“代码永远不会被触达”。
人生中往往会有许多意外,面对着很多的不如意,而人们对于意外遭遇的失败,一定会有很多话想说。可是,严密的“社会规律”就会像这段程序一样压制你说不出口——因为没有一个需要触发你说出这种话的条件。
你是选择打破规则,勇敢说出,还是选择烂在肚子里?也许网络上激昂的文字会煽动你努力呐喊,不要做一个懦夫。但你需要明白,需要呐喊的时候,自会有天意触发,如果已经感受到了规则选择不要说出这些话,还是烂在肚子里比较好。
试想你写的最后的战败感言某一天打印在了程序上,你会觉得乌龟很勇敢吗?答案我觉得每个人都可以有自己的想法。至少在作者我看来,乌龟只是我写的一段代码,这段不该执行的代码获得了执行,程序一定有问题。