程序员面试白皮书

978-7-115-40184-7
作者: 董飞 逸超
译者:
编辑: 陈冀康

图书目录:

详情

这是一本介绍程序员面试的参考书,通过一系列的实例介绍了数据结构、算法以及计算机专业的其他基础知识。同时,本书还在各章中及时回顾教材中的重点内容,书中的题目也很据参考价值,通过实例与知识点相结合的方式帮助读者掌握要领。除此之外,本书还将引导读者分析题目,帮助读者理清思路并最终解决问题。

图书摘要

版权信息

书名:程序员面试白皮书

ISBN:978-7-115-40184-7

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


逸超

竞赛保送国内Top2大学本科,毕业后前往加州大学攻读硕士学位,期间获得全额奖学金。毕业时获得十多个知名科技公司offer,现在在硅谷就职于顶尖科技公司,从事软件开发工作。擅长总结面试方法,乐于帮助朋友准备面试。

虾米

国内TOP2高校毕业,赴美硕士毕业后跨专业应聘程序员工作,有一套自己的面试方法学。现于硅谷市值最高的公司之一任软件工程师,业余时间开设面试讲座,在圈内小有名气。

笑笑

国内top2大学本科,UCSD计算机硕士。现苹果公司软件工程师。曾拿到多个硅谷顶级软件公司的offer,面试经验相当丰富。

董飞

本科南开大学,硕士杜克大学计算机系毕业。在攻读硕士期间,从事跟Hadoop大数据相关的研究项目,在VLDB,SOCC顶尖数据库大会发表过论文, 先后在创业公司酷迅,百度基础架构组,Amazon 云计算部门,Linkedin担任高级工程师,负责过垂直搜索引擎,百度云计算平台研发,广告系统和在线教育平台的架构。在大数据领域业界研究多年,涉及Hadoop调优,分布式框架,Data Pipeline, 实时系统。目前在线教育创业公司Coursera从事数据工程师工作。

在多年工作中,除了对技术的不懈追求,也积累了大量的面试经验,拿到北美热门公司10+ offer。在Linkedin期间,也积极参与面试过近200人,全公司前三的面试官,乐于分享并帮助很多人成功求职,实现目标。


本书是程序员和IT从业人员的面试求职指南。本书遵从大多数面试参考图书的组织方式,结合实例,按照常见的数据结构、算法以及计算机基础知识进行章节划分。每一章的“知识要点”部分介绍章节涉及的相关知识点,回顾重要的基础知识点;“模式识别”部分给出一些例题,帮助大家总结解决相关问题的常见方法,并且通过分析问题中的关键信息,教授读者如何从题目中分析题型和解题方法。程序员面试是对于面试者计算机知识的全面检测,因此,本书设有专门的章节覆盖了网络、操作系统、编译器、算法和数据结构等各个领域的知识。

本书作者来自硅谷一线的IT公司,书中包含了作者亲身的经历和体验,书中收集的题目部分来自互联网上分享的面试经验、在线编程网站leetcode,以及一些著名的面试参考资料。本书适合想要从事正规的程序员、架构师以及相关IT公司的专业人士和学生参考,尤其适合那些以一线IT外企或互联网公司为求职目标的读者阅读。


这是一本我希望自己在大学就能看到的一本书。在我读大学的时候,跟很多同学一样也走过不少弯路:艰难地啃着计算机必修课,被里面的指针和对象搞的晕头转向,对i++和++i区别死活不理解,为操作系统的调度策略而抓狂,很难对专业书产生兴趣,只是想着去应付考试和学分。当我们毕业后,虽然有了计算机学位和实际工作经历,但其实还是不知道最想得到什么。我当时心中有个情节,就是希望能去最好的公司,比如Google,因为听说那里面都是最聪明的人,有着最好的待遇和福利,做着最有影响力的事情。当我鼓起勇气去尝试的时候,我失败了,并且要进入6个月的冷藏期(失去在一段时期内继续面试的机会)。而我发现当时的面试表现是那么的稚嫩和糟糕,我开始懊恼,开始反省,开始重新准备,这样才有了我下一个面试机会和其他的Offer。当然如果一切可以重新再来,我可以更有自信更好地发挥我的能力,也许当时的理想公司就会给我Offer。

有些朋友会认为只要能混过面试,拿到工作之后有的是时间可以继续学习。这话听起来有道理,但我在这里给出一个反例:我记得多年前第一份实习的任务是对某个大型应用程序进行性能测试。我不知道如何创建一个用户界面,然后随意定义文本字段、菜单和按钮。我不知道如何用线程来思考,我错误调用整个缓存和线程池。我也不知道如何去做代码维护,并且没有单元测试和编写基本的文档,最后我还是写了几千行的Java代码,这是个无法维护的巨大的类。而如果我在工作之前多一些积累和看一些代码,或许不会那么尴尬。

也有些同学说面试中只会考没有用的算法,这跟工作没有任何直接关系。我同意工作中大多数情况是不会用到复杂的算法的,但如果你没有过硬的基本功,在面对一些新情况的时候,你就很难举一反三,灵活运用了。我记得我在第一家公司第一个项目是在一个新城市中增加新的排序选项来选择上市的所有租房。这是一个紧急任务,上司希望我尽快熟悉代码库,我当时也顶着压力,做到了一周上线。不久后,我就在总裁面前演示:我看着他点击了某个区的房源,选择了新的排序选项,结果花了几分钟去加载页面。我之前也验证过应该没问题,平常只需要几秒钟的时间。我当时满头大汗,真是搞砸了。那天晚上,我思考了很久才想通。我选择的新代码做两个数据库调用需要遍历其中的每一个,它需要的n * log n比较的次数,而对于那个区域,其中大约有n =1000个房源,那么大约要2万次数据库调用才能完成一个页面加载。当然,知道了原因,优化起来就简单了,通过调用缓冲,把数据切成更小块,做数据量的控制,最后性能提高了100倍,所以说系统优化是离不开算法和扎实计算机基本功的。

其实每个工程师都讨厌Bug、代码不整洁、性能太差、用户界面不人性化等,这些都是一些技术细节,是可以慢慢体会和提高,总能找到答案去改进的。但在工作中,我应该学习和使用什么样的技术?为什么要自动化测试?如何搭建一个产品,看起来比较靠谱?我怎么去选择一份工作?如果我在一家大公司工作,如何跳槽到创业公司?我如何谈判取得更多的薪金或奖金?什么是股票激励?这些问题倒是更棘手,我也会在第1章给出一些介绍和辅助工具。

回看我走过的一路艰辛,我尝试反思学到了什么,我发现其中大部分经验都来自痛苦的反复试验的结果。当我意识到成千上万的面试者或者IT开发人员正在经历同样的试错,犯同样的错误, 我觉得应该做一些更有意义的事情:这本书就是一个工具。诚然,有些教训只能从在自己的错误中学习,但我希望本书能够帮助你从别人的经验中获得通向成功的捷径。

俗话说凡事要“顺势而为”,找工作亦是如此。现如今,借助手机网络带宽的快速提升以及移动互联网的概念,原先在PC平台才能开展的服务一下被冠上了“移动”二字。在手机上使用服务和计算机上使用服务,在本质上并没有太大区别,但关键在于手机更具有“私密性”和“便携性”,大大增加了客户粘性和使用时间,进而会对服务提供商产生更大的依赖性。

在中国,互联网公司中百度、腾讯、阿里巴巴“三架马车”分别把持搜索、社交游戏和电商平台三大主战场,互相竞争。而硅谷更是百花齐放:Apple、Google、Microsoft致力于打造自己的生态圈,完成硬件、软件、服务的闭环;而Facebook、Twitter、LinkedIn等为代表的社交平台也迅速通过巨大的用户群体完成“圈地运动”,将管辖区域内的用户导向各个实体商户;更有Uber、Airbnb等新兴公司,致力于通过移动互联网思维改变人们的实际生活。

相比于2000年左右的互联网泡沫,这次的计算机高潮来势更为凶猛:不单单提供资讯、门户、电邮等虚拟线上服务,而是直接破坏性地侵入传统行业,以更高的效率改变原有行业。这就是为什么许多新兴科技企业号称是技术公司,但实际上提供着传统行业的服务。当前的趋势也会逼迫着传统公司作出改变,引入更多计算机人才,利用云计算、机器学习等新手段与新兴公司竞争。最简单的例子如Wal-Mart Labs,它以一个科技智囊的角色隶属于Wal-Mart,通过计算机技术分析,优化Wal-Mart的营运效率。金融、银行、地产、石油、制造、电子硬件等各个行业也纷纷引入计算机技术,大大创造了从业人员的工作机会。

这样的趋势对你我有什么影响?人才需求的极速扩张意味着找工作难度降低,并且待遇也是水涨船高。举例来说,在美国,硕士毕业加入Apple、Google、Facebook等公司起薪至少10万美元,外加股票期权。更不要说加入最火的创业公司,三四年后一旦上市就可以提前退休,或者把工作作为兴趣。在国内,阿里巴巴上市也造就了成百上千个千万富翁,即使是上市前一两年刚加入的新人,也拿到了100万人民币左右的股权。

如果说这些职位难度太高,对于你遥不可及,或者需要很长的准备时间,那也许对于上面的文字你只会一笑而过。但是,如果告诉你通过正确的方式,做好面试准备,上面所说的职位触手可及,是不是听起来更有吸引力了呢?事实就是,由于软件工程师的职业特性、面试要求及局限性,以及市场需求等因素,程序员求职是一种比较具有应试性、相对容易找到门道的简单职业道路。不乏相关或不那么相关专业的毕业生通过半年到一年的努力拿到理想的IT行业的相关工作的事例,由此可见,挑战不在于“能”和“不能”,而是如何通过正确的方法、迅速地赶上潮流分一杯羹。

本书的目的并不在于代替课本教材,系统性地讲授计算机技术,而是作为一本工具书,创建一个实际的、可操作的面试方法论教程,提供一条快速熟悉技术面试题目的捷径,并且针对不同类型的题目,归纳总结解题方法。

程序员面试是对于面试者计算机知识的全面检测,因此,关于计算机诸如网络、操作系统、编译器、算法和数据结构等各个领域的系统性学习不可或缺。但是考虑到面试的局限性,诸如时间限制,面试官对于面试者的熟悉程度等,在白板(或者白纸)上写程序解决一些算法问题成为面试官较为青睐的方法之一。由于该面试方法比较机械,相对容易准备,也最适合总结一些方法论,所以本书的目的就在于传授白板写代码的准备技巧,帮助大家通过面试。在本书中,我们将会遇到的题目、技术,都是来自于我们实际面试过的一些炙手可热的硅谷公司和我们自己作为面试官的一些心得和宝贵经验。正如参加GRE考试一样,关于考试技巧的书籍并不能让一个完全不懂英语的人通过考试,但是可以使得英语基础合格的人如虎添翼,大大增加通过考试的几率。这就是本书的全部意义所在。

市面上关于程序员面试的参考书也不少,但是我们认为这些书的关键问题在于它们大多是教你“怎么做”,但很少涉及“为什么这么做”。于是,读者往往会觉得书中的解法十分精妙,但是在面试的时候完全想不起来用哪种方法解决问题。其根本原因在于,这些参考书代替你做了最关键的一步:判断用什么方法解决当前的问题。

本书遵从大多数面试参考书的构成方式,结合实例,按照常见的数据结构、算法以及计算机基础知识进行章节划分,但是,本书着眼于如何进行“模式识别”,通过分析为什么这个问题被划分到这个章节,来教大家如何判断实际面试问题的类型,并且顺水推舟地得出解决问题的方法。每一章的“知识要点”介绍章节涉及的相关知识点,回顾通常出现在教材中的重点内容;“模式识别”给出一些实例,帮助大家总结解决相关问题的常见方法,并且通过分析问题中的关键信息,教授大家如何从题目中得到关于题型分类以及解题方法的蜘丝马迹。

本书收集的题目部分来自互联网上分享的面试经验、在线编程网站leetcode,以及面试参考资料Cracking the Coding Interview和Element of Programming Interview。如果你认真准备过面试,可能会对题目有似曾相识的感觉。但本书的关键不是教会你做一道题目,而是教会分析题目、解决题目的方法,从而学会解一类题目。具体的题目不是关键,从题目到方法的思维过程,是本书努力想传达的重点;最后,“工具箱”部分给出该章涉及的C++/Java类,它们的常见函数及使用方法,还提供一些标准库函数,以及相关参考资料或扩展阅读。

如果你有志于投身到滚滚的IT互联网浪潮中,无论你是一个学生,还是初级程序员,不论你以后是定位于架构师还是项目经理,你都需要一块敲门砖,那么这本书就是为你量身定做的。作为有着在国内外创业公司和一线公司经历的过来人,我们希望本书能给你职业生涯上添砖加瓦,帮助大家到达理想的彼岸。

最后,我们特别感谢Ruthia百忙之中抽空帮助设计封面。正如封面中锤子所象征的那样,每个人都需要付出持之以恒的努力才能获得成绩,在此与读者共勉。

由于水平有限,编写过程中难免产生疏漏。如果在阅读本书的过程中你有任何建议和问题,请联系我们:UltimateGuideToCodingInterview@gmail.com。


整个招聘流程主要如下:申请某个公司你感兴趣的职位,投出你的简历。HR从简历库中筛选符合要求的简历,安排面试。面试主要分为电话面试和现场面试,如果面试表现优秀,HR会同你讨论待遇、福利、起始时间等具体信息。针对上述流程,让我们一一分析其中的关键环节。

简历是求职的第一关,尽管简历不能决定最后的录取结果,但是一份结构清晰、内容充实且具有针对性的简历,可以给你带来宝贵的面试机会。本节将从格式、内容安排和描述技巧等方面介绍如何生成一份对HR有吸引力的简历。可以根据不同的职位描述适当更改简历的某些内容,但不建议准备太多份区别过大的简历,以免自己投递的时候产生错误。如果你真的需要这么多简历以应对不同职位,则应当考虑下自己的优势在哪些方面,适当减少求职目标。注意,下文的描述注重在北美求职的简历结构,其中大部分要点具有普适性,但是如果在国内求职,有些地方可能需要根据实际要求进行更改。

除非你想面试用户体验或者设计相关的职位,否则简历的格式尽量以简介清晰为主。标题及名字等重要信息可以适当加粗或者增大字体,其他文字描述尽量统一字号。字体选定一种即可,不建议用不同的字体去突出不同的内容:不同的字体会显得版面杂乱,并且对排版造成困难。英文简历Calibri是比较适宜的字体,中文可以用宋体。简历可以用Word、Latex、Pages或者InDesign制作,但是最后务必导出成PDF,确保在不同的平台上,对方看到的格式一致。

简历是一个提供信息、展示自己的平台。对于刚毕业、没有什么工作经验的人来说,简历一般控制在一页为宜,如果是PhD,需要适当列举一些相关的文章发表信息,那么简历可以扩展至两页。这里就给一个示例,它在一页纸的长度中精炼地描述了求职者的教育背景、实习经历、技能和专业背景,如图1-1所示。

图1-1 一页纸的简历

简历的第一要务是让对方能够认识并联系上你,所以名字、邮件、电话、地址等基本信息缺一不可。特别的,对于在美国本地求职的人而言,邮编很重要,因为网上的申请系统往往会根据邮编将申请者按地域划分。对于很多公司而言,他们会优先考虑本地的申请者。所以当你申请的公司在当地有总部/分部时,务必写上本地的邮编。

这里有个小技巧,由于绝大部分科技公司都在加州,特别是北加州硅谷附近,所以如果有朋友在加州的话不妨写朋友的地址。这样做的确可以提高被选中面试的几率,甚至有些小公司可能会跳过一轮电话面试直接邀请你去公司面试。现在绝大部分面试过程都是通过电话或邮件确定,除了最后给你发Offer,招聘的中间部分都不会给你提供地址寄送任何文件。如果公司决定给你Offer,你也完全有机会和HR确认/更新你的实际地址。这样做的缺点是,可能去公司面试的时候你需要自己安排机票住宿,如果真到了这一步,权且就当花钱买个机会了。

基本信息之外,对于刚毕业的学生而言最重要的信息包括学校、专业和学位。学习成绩对于大部分公司而言只是加分项,如果GPA低于3.3,可以考虑不包括成绩。当然,如果GPA是你的亮点之一,那也完全可以包含此信息。在这方面,Oracle是出了名的名校控,如果你高GPA、名校出身,基本上半只脚已经踏入了Oracle。相对而言,其他公司并没有这样的要求。此外,对学生而言可以列举一些在校学过的相关课程。只需要列举课程名即可,内容数量以5项左右为宜,课程名尽量选择大家熟知的,比如算法、数据结构、操作系统等,如果是研究生课程,可以加上“高级(advanced)”关键字。

简历中另一个十分关键的内容是之前做过的项目描述,包括工作经历、实习经历或者课程项目经历,这些部分的目的在于展示你具有相关经验,具有较强的技术实力,能够加入团队一起完成一个复杂的项目。这里,我们主要介绍如何选择合适的项目,在描述技巧部分,会进一步介绍如何描述使得你的项目更有趣。就项目内容而言,你需要优先选择和职位描述相关的项目,相关性包括:需要相似的知识,需要使用相同的软件或开发环境,需要类似的编程语言或编程模式,需要实现类似的功能等等。这些项目最能体现你的价值,使得你从一堆申请者中脱颖而出。如果没有相似的经历,那么你可以列举一些比较复杂的项目,突出你的综合能力。这些可以包括:毕业设计、课程的学期作业、网上参与合作的开源项目等。列举的目的主要是突出你的技术水准优秀,具有与他人合作的能力。就项目种类而言,你需要优先选择业界的工作实习经历,只要它们和你所求职位的描述大体在同一个行业即可。毕竟,有实际的工作经验可以传达下列信息:你对业界有一定的了解,熟悉业界的开发模式和开发周期,能够适应公司的工作环境。

简历的最后部分可以用来列举你的技能,包括熟悉的编程语言、开发环境、技术强项等。这部分的目的在于让HR能够从简历库中匹配到你的信息。通常,每个职位都有一些技术要求,HR会通过查询关键字,从简历库中选择匹配程度高的简历。这部分可以大大增加简历被匹配上的可能性。列举的原则是,并不需要特别熟悉,只要实际用过就可以在此列举。注意,如果你有幸被安排了面试,一定要回到这个部分,确保你所列举的部分至少都能回答一些基本的问题,千万不要给人做假的感觉。往往,HR并不一定了解你项目部分的描述是否与职位要求一致,因此,你这部分所列举的技能需要尽量用业界标准的语言,列举名词即可。

描述的技巧主要体现在项目描述方面。项目描述主要突出你做了什么,实现了什么样的目的。项目名称一般需要让读者大致了解你做了什么,然后以如下模版,“通过……开发方式(或者技术),做了……,最终实现了……的结果”,描述项目的具体内容。就英文简历而言,一般以过去时为主,以动词开头,描述你做过了什么,实现了什么目的。举例如下:

Software Engineering Internship,XX Company,6/1/2014 – 9/1/2014

Interned with the server team.

Implemented a distributed access control algorithm in C++, which improved login time by around 50%.

英文简历常见的另一个问题是如何翻译专有名词,比如在国内大学获得的种种荣誉等。此时,一定要参考网络资料,确保读者的理解和你想要表达的意思一致。甚至可以用一句话简单描述这是怎样的荣誉,或者用百分比表示只有top的学生才能获得该项荣誉。举例如下:

Excellent Student Award(top 3%)

Granted to recognize overall outstanding performance.

另一个很好学习途径,就是去LinkedIn上看一些优秀人士的个人主页,特别是你想去的公司的工程师的背景。一般都会很清晰地构建他的目标和过去经历,不需要照搬内容,但可以给你启发,当你去投这些公司时,你就知道什么样的简历更容易被他们欣赏。

根据面试的不同对象,在招聘过程中你可能需要面对 HR、技术面试官和老板。针对不同的角色,你应该准备不同的面试方式。具体分析如图1-2所示。[1]

面试官

他想要知道

可以向其询问

人力资源

你是谁?你的职业兴趣是什么?

公司的整体信息和组织结构;开放的职位

工程经理

你做过什么项目?具备什么技能? 对什么项目感兴趣?

团队的职责是什么?团队目前和将来会做什么项目?团队在找什么样的人?

产品经理

对公司产品的观点/反馈/建议。如果让你设计一款产品,你会怎么做?

公司的下一步产品是什么?公司面临的关键性挑战是什么?公司中的工程师如何与产品经理交互?

午餐面试者

你之前或当前公司/学校的团队怎么样?你喜欢他们吗?为什么?你怎样融入公司的文化?

公司中的团队是怎么样的?他们有哪些团队构建活动?

工程师

如果你能够提出合理的清晰的问题,如果你能够有效地表达你解决问题的规划,如果你最终能够解决这个问题——那么,请展示你的代码

一般的工作流程是怎样的?公司使用的技术栈是什么?

架构师

你是否能够以可扩展的方式解决问题?你是否能够认清系统设计中的关键权衡?

公司使用的技术栈是什么?公司如何使用这些技术来解决现实世界的问题?

图1-2 面试须知

HR是你与公司的连接点。通常,HR负责安排协调面试,主要通过邮件联系。HR也有可能会直接打电话联系你,目的是了解你的基本情况,包括身份、毕业/离职时间等。HR通常会介绍职位要求和公司的基本情况,并且在面试当天接待你,了解你是否有其他面试安排或者其他公司的Offer。此外,HR还负责面试你的沟通能力,向老板反馈性格方面与团队的契合度以及对公司感兴趣的程度。因此,每次与HR的沟通也需要热情、职业。适合向HR了解的信息包括:公司的整体氛围、面试的流程安排、最近公司人员流动情况等。

技术面试官主要负责衡量你的技术水平,以及判断你是否符合职位要求。总体而言,对科技公司,技术面试官的意见最为重要。技术面试包括电话面试和现场面试,前者主要偏向概念性的问答,也包括通过协作网站直接写代码等。现场面试通常包括白板写代码,解决一个算法问题或者设计问题等。本书的主要目的就是帮助你通过这轮面试。

一些面试的小技巧如下:一定要先沟通,明确自己了解题意,不要过分考虑或者欠考虑。首先可以给出一个比较容易想到、但并不是最优的解决方案,再逐步优化。在思考的时候也要把思路讲出来,哪怕不是很成熟的方案。一旦遇到困难,可以先自己设法解决,如果五分钟没有思路,可以向面试官求助。适当的提示并不会影响你面试的最终结果。当开始写程序的时候,尽量注意语法格式、变量命名等,避免写伪代码,越接近真实代码越好。写完以后自己检查下有没有明显的错误,可以列举几个简单的测试数据,与面试官一起检验一下整个运行过程。

面试是一个合作解决问题的过程,沟通一定是面试的关键:需要通过沟通展示你的逻辑性、理解能力和表达能力。在面试的最后,通常对方会给你提问的机会,你可以问的问题包括:团队平时使用什么样的技术,通常的工作压力和工作时间,公司最让人兴奋的地方;在当前职位工作了多少年,面试官之前的工作经历与现在相比有什么异同等。

面试考察的基本功,包括以下方面:

技术面试的流程通常如下,可供参考。

当你拿到一个具体问题时,可以按照以下流程回答:

1.明确题意:通过与面试官交流明确需要解答的问题。这部分主要为了让自己放松心态,并且给面试官留下你具有良好团队意识和交流能力的印象。

2.描述大体思路:描述你打算用什么算法,什么数据结构。主要是为了让面试官了解你的思维过程,如果你给出的解答与他想要的答案偏差太多,可以及时纠正。同时,描述思路也给了你自己思考的机会。

3.实现算法:先处理边界条件。对于重要的算法模块,加一些注释或者与面试官进行交流。目的是让面试官始终了解你在做什么,算法框架是什么。

4.跑一个测试:用一个测试用例走一遍你写的程序。目的在于和面试官一起确保你的算法是有效的,可以在过程中及时发现并纠正自己的错误。同时,给面试官留下你有写单元测试(unit test)习惯的良好印象。

5.描述算法复杂度,回答面试官的问题。

团队的老板通常最后一个出场面试,或者陪同面试者一起吃午饭。老板负责收集整理所有人的反馈,并且决定是否发Offer。通常而言,老板可能不会问过于技术的问题,而是侧重考察你的协作沟通能力。老板的问题可能包括:如何面对工作中的难题/压力,你之前做过的项目,为什么适应这个职位等等。与老板沟通需要表现出你对他们团队的热情,并且在回答中尽量体现自己为什么适合这个职位。面试是一个相互的过程,通过与老板的面试,你需要了解这些问题:团队的成员构成,一般情况下项目如何分配,老板对你的期望,老板对团队在公司中发展的一些展望等等。

另外,准备一些常见的行为问题:比如你有没有过失败的经历,如果你老板给你不喜欢的任务怎么办,你想象中要成为什么样的人。这里一方面可以结合自身精力,另一方面多关注公司的介绍页面,包括公司创始人背景、企业文化、招聘的要求。这些都可以提前做好功课,尽量体现出来你的激情、负责、勤奋等优秀品质。

如果走到这一步,那么祝贺你,你成功了!在这一步,你需要一些谈判技巧,为自己争取更多的利益。首先,你要做的是与HR核对信息,包括你的地址、入职时间等。

通常,HR会简单介绍你的待遇福利,当你确认无误后,HR会生成正式文档让你签名。在这个阶段,你可以让HR解释Offer条约中你不理解的部分,并且协商你的待遇。协商的最常见方式是,当你有其他公司的Offer,你希望最想去的公司能够match其他公司的最高值。注意,在这个阶段,HR是与你站在一条战线上:HR也不希望你轻易地拒绝他们的Offer。因此,你完全有理由提出你自己的要求。一般在你有其他公司Offer的情况下,HR都能争取到一些更多的利益。从争取难度而言,入职时的签字奖金最容易争取,股票和基准工资则比较难有提升。当然,工资待遇是重要的一方面,但在你决定是否接受Offer的时候,综合考虑公司的发展前景、团队在公司中的地位、老板与你交流时你的感受、团队氛围等也是必不可少的因素。

对于美国的绝大部分公司,Offer上都不会写雇佣时间,这意味着双方都可以随时终止合同。通常情况下,大公司不会轻易裁员,哪怕裁员也会有一定的补助。另一方面,这也说明你可以随时离职,甚至在入职之前,也即毁约。一般来说,不建议这种做法:更合理的做法是尝试与HR沟通,告知对方自己还有其他的面试/Offer,需要推迟一段时间做决定。如果实在万不得已,有其他更好的选择,你需要尽早与HR沟通,希望对方理解。一定不要拖到最后告诉对方自己不去了,这样的做法很不职业,也不礼貌。

当你接受Offer之后,可以向老板要一些材料,自己先准备一下,以便工作开始的时候能够更快上手。一般新到一个公司都会有数周甚至数月的上手时间,团队会专门有人帮助你了解他们的项目。新的旅程就此开始!但这仅仅是开始,未来也许是更大的挑战,能不能融入团队中,能不能抵抗住压力,工作内容是否符合自己的兴趣,这些都是未知数。所以我们说没有绝对正确的选择,只要用你的才华和汗水付出才有实际意义!

问题1:如何知道一些靠谱的公司?

首先,了解一下“牛人”都选择去哪些公司。如果公司名气不大,可以去流量排名上去看他处于什么地位,公司有没有上市,它的融资规模,还可以从Linkedin看它的员工是否优秀。

在硅谷,大家非常热情地谈创业谈机会,我们也通过自己的一些观察和积累,看到了不少最近几年才涌现出来的热门创业公司。给大家一个列表,这个是华尔街网站的全世界创业公司融资规模评选(http://graphics.wsj.com/billion-dollar-club/ )。它本来的标题是“Billion Startup Club”(十亿美金创业公司俱乐部),不到一年的时间,截至2015年1月17日,现在的排名和规模已经发生了很大的变化,如图1-3所示。

第一,估值在10Billlon(百亿美金)的公司达到了7家,而一年前一家都没有。第二,第一名是中国人家喻户晓的小米,第三,前20名中,绝大多数(八成)在美国,在加州,在硅谷,在旧金山!比如Uber、Airbnb、Dropbox、Pinterest。第四,里面也有不少以相似模式取得成功的公司,如Flipkart就是印度市场的淘宝,Uber与Airbnb都是共享经济的范畴。所以大家还是可以在移动(Uber)、大数据(Palantir)、消费级互联网、通信(Snapchat)、支付(Square)、O2O App里面寻找大的机会。

图1-3 十亿美元创业公司俱乐部

问题2:硅谷的Startup有什么技术方案?

分类介绍如下,如图1-4所示。

编程语言:Python、Scala、Swift for iOS、C/C++、Java等主流开发语言;

前端:Play、Video.js、Jade、HTML5等;

框架容器:Docker、Mesos、Vagrant等;

日志监控:Datadog、Sumologic、Akka、Kafka等;

后台数据处理:Hive、Scalding、EMR、Big Query等;

图1-4 硅谷常用技术矩阵

虚拟机:EC2等云服务;

服务器:Nginx等;

配置工具:NPM、Zookeeper、Puppet、Gradle等;

信号通知:SQS等;

代码托管:Github、SVN等版本控制工具;

数据存储:Cassandra、MySQL、S3、Redshift等;

内部工具:Phabricator、Slack、Google Docs、RelateIQ、Jira等协作工具。

以Coursera为例,作为创业公司,Coursera力图保持敏捷和高效。从技术上来说,所有的内容都是在基于AWS开发,可以想象随意启动云端服务,做一些实验。公司大致分成产品组、架构组和数据分析组。因为公司比较新,所以没有什么历史遗留迁移的问题。大家大胆地使用Scala作为主要编程语言,采用Python作为脚本控制,比如产品组就是提供课程产品,里面大量使用Play Framework、Javascript的Backbone作为控制中枢。而架构组主要是维护底层存储、通用服务、性能和稳定性。笔者所在的数据组,一部分是对商业产品、核心增长指标做监控、挖掘和改进;另一部分是搭建数据仓库,完善与各个部门的无缝数据流动,也用到很多技术;例如使用Scalding编写MapReduce程序,也有人做AB testing框架、推荐系统,尽可能用最少人力做有影响力的事情。其实除了开源世界,Coursera也积极使用第三方的产品,比如Sumologic做日志错误分析,Redshift作为大数据分析平台,Slack做内部通信。而所有的这些的目标就是想解放生产力,把重心放到用户体验、产品开发和迭代上去。

问题3:什么时候才知道准备好面试?

可以从如下几个方面来衡量。

算法是否过关,是否能写出递归和动规;

Coding是否过关,是否能在编译器中写出Bug Free;

Design是否过关,是否能给出Tradeoff;

项目经历整理,能够流利说出架构、难点、自己的贡献;

加分项:Github、Blog、参与Open Source。

问题4:如何拿到美国工作签证?

要来美国工作,一般是要求具有H1B(工作签证)的身份,获得该身份需要有雇主向劳工局提出申请(sponsorship)。根据现在的形式,每年的名额都是一抢而空,那么这就需要抽签决定。在4月1日之前提出申请,4月1日之后开始抽签,如果是在美国获取硕士以上的学位,可以有优先级,抽取概率更高,而根据今年情况,普通的抽中几率是50%。即便没有抽中,如果是拥有美国的硕士学位,可以使用OPT照样工作,并且可以省社会安全税(Social Security Tax)。而如果是海外的学位,只能等来年再抽签。

像Google、Facebook这种全球性公司,他们也会提供其他国家办公室的机会,工作一年后再通过L1或者H1B继续到美国工作。另外如果你抽中了H1B,那么如果以后再跳槽,则可以通过办理转职(transfer)沿用之前的名额,而不需要再次抽签。H1B每3年可以续一次,最多6年。如果H1B到期时已经申请绿卡,那么还是可以延长H1B的有效时间,直至绿卡生效。

问题5:我不是算法大牛,不是ACM队员,听说Google,Facebook有很多牛人才能进,那我怎么能拿到好Offer?

首先要有信心,算法不是想象那么难。原因有以下两个方面:

第一,因为面试常见的算法就那么几种。只要你努力去总结归类相似题目,只做很少的题,就可以举一反三掌握很多的题。不要盲目关注数字。做题质量非常重要。标准是:你做过的题目,让你再做一次,你就能“完美解决”。

第二,即使你知道一道题的解法,你未必能写好。因为你可能每次写出来的程序都很随性,这样会漏洞百出。程序员是一个非常讲究严谨性的职业,如果你在总结题目的时候能够找到这些题目的模板,把模板提炼好,碰到类似的题目,可以一边写模板,一边想想怎么在模板上做一点简单的改动。这样既节省时间又保证不会出错。

问题6:从其他专业转做计算机专业的该怎么准备?

1.让自己更专业。例如,你的简历只能放和计算机有关的东西,其他东西再牛也不能发挥用处(如学生会主席)。如果简历还是很空,就多去做项目。实在没项目,就把非计算机专业的项目改写得更接近。

2.在某一方面达到工程师实力。临时转行时间短,找一个容易入手的准备,如果你以前做的事情跟数据有关,就申请数据分析师(Data Analyst)。如果你本来就会一些基本技术,可以做前端,用JavaScript、HTML和CSS,去真正做一个自己博客。如果对产品感兴趣,就玩Django、Ruby on Rails这样的网站框架,了解一个网站是怎么搭建起来的。如果对移动开发感兴趣,就写几个在iOS或者Android上的App。这样做的好处是,简历不空,如果问到,可以驾轻就熟。如果不相关,坦诚相见,说由于我是转行的,在这方面不熟悉,可以尝试一下。也可以直接告诉面试官,我是转行的,我对计算机很感兴趣,做了这么这么几个项目。于是面试官不会问你难题。而实际上你早就准备好了,超出面试官预期,会得到一个面试高分!

问题7:面试时候如何表现自己体现沟通能力?

首先你要站在面试官的角度思考问题。面试官要招你进去当同事,你希望同事怎么样?

你可以反复和面试官交流自己的想法,得到面试官认可以后再动手写。可以讲讲你是怎样想到这个思路的。从而展现你的沟通能力。记住,你并不是要说服他接受你的想法,而是要把你的想法解释给他听。面试官提出质疑的时候,第一,不要觉得面试官什么都不懂,怎么这都不知道(其实他只是看一下你是否真的懂);第二,面试官比你经验丰富得多,很有可能就是你犯错了,赶紧想想是不是真的有问题。

问题8:面试中出了Bug怎么办?

避免Bug很重要,这个需要我们平时不断地练习,按照上述的方法准备,还是可以避免一些“坑”的。但碰巧你可能不在状态,写出了Bug被面试官指出,是不是就挂了呢?

首先别担心,出Bug很正常,也许面试官来面试你之前正在Debug。衡量一个程序员能力的标准,并不是他能想出多牛的算法,而是程序员在遇到问题的时候分析和解决问题的能力。而出Bug的时候,正是展现你是否是一个合格程序员的时候!

Debug的流程如下所示:

1.通过测试用例定位Bug所在位置;

2.不要立即修改代码,重新梳理逻辑。因为很有可能还有其他Bug;

3.走完所有逻辑之后,心里有数怎么改了,再动手开始改;

4.用测试用例再走一次新的代码;

5.在整个过程中,不停地告诉面试官你在做什么(在不影响正常写程序的情况下)。

这样,成功排解Bug,不但不会减分,还会因为你优秀的Debug能力和与此同时展现出来的沟通能力而加分。

问题9:如何做出最后选择Offer?

在考虑Offer之前,先对公司做个研究,比如这家公司是什么规模,产品是什么,Glassdoor员工如何评价的,你的职位你喜欢吗?这就跟选学校一样,如果选错了,也是需要走很多弯路。我们个人的参考是首先这家公司是上升期的,产品是否有爱,团队是否比较强,能否学到东西。对公司分类,例如Hortonworks这种是纯技术性的,面向企业级的,可能没多少人知道,而Uber是大众消费性,很多朋友都用过。现在的热点是移动互联网,大家也可以多考虑这一块。

如果上市的公司,会给限制性股票,分3~4年行使期权,创业公司一般给期权,不同就是限制性股票是白送的,不需要自己掏腰包,期权需要自己买入,不同时期价格不同,但股票交的税非常高,有些期权是长期避税的。最后也要考虑你的兴趣和对风险的承受能力,如果去大公司做个螺丝钉,实现共产主义生活也无可厚非。去小公司压力大,成长快。但也要做好失败的准备,看看当年Zynga教训。

了解了面试的基本过程,让我们回到正题,按章节梳理技术面试的要点。

本小节列出求职、面试和考虑Offer的整个过程中,可以参考的一些有用的网站和资源。

1.求职

Glassdoor

http://www.glassdoor.com

LinkedIn

http://www.linkedin.com/jobs

Indeed

http://www.indeed.com/

CareerBuilder

http://www.careerbuilder.com/

Monster

http://www.monster.com/

2.代码

A Short List of DevOps Tools

http://newrelic.com/devops/toolset

TopCoder

http://www.topcoder.com/

Google CodeJam

https://code.google.com/codejam

CodeChef

http://www.codechef.com/

HackerRank

https://www.hackerrank.com/

ACM ICPC

http://icpc.baylor.edu/

hackathon.io

http://www.hackathon.io

Hacker League

https://www.hackerleague.org

Hackathon Hero

http://www.hackathonhero.com/

3.行业趋势

Y Combinator

https://news.ycombinator.com/jobs

AngelList

https://angel.co/jobs

Reddit

https://www.reddit.com/r/Jobbit

StackOverflow

http://careers.stackoverflow.com/

The Distributed Developer Stack Field Guide

http://sites.oreilly.com/odewahn/dds-field-guide/

4.代码质量

Continuous Integration

http://martinfowler.com/tags/continuous%20integration.html

Java Code Review Checklist

http://java.dzone.com/articles/java-code-review-checklist

Stop More Bugs with our Code Review Checklist

http://blog.fogcreek.com/increase-defect-detection-with-our-code-review-checklist-example/

Embedded System Code Review Checklist

http://users.ece.cmu.edu/~koopman/pubs/code_review_checklist_v1_00.pdf

Typesafe Project & Developer Guidelines

https://gist.github.com/jboner/3864996

List of tools for static code analysis

http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis

Security Source Code Analysis Tools

https://www.owasp.org/index.php/Source_Code_Analysis_Tools

5.团队合作开发

Slack

https://slack.com/

Google Apps (GMail, GChat)

https://www.google.com/work/apps/business/

IRC

http://en.wikipedia.org/wiki/Internet_Relay_Chat

Yammer

https://www.yammer.com/

Asana

https://asana.com/

Microsoft Project

http://products.office.com/en-us/project/project-and-portfolio-management-software

JIRA

https://www.atlassian.com/software/jira/

bugzilla

https://www.bugzilla.org/

GitHub Issues

https://github.com/blog/831-issues-2-0-the-next-generation

Confluence

https://www.atlassian.com/software/confluence

DropBox

https://www.dropbox.com

Google Drive

https://www.google.com/drive/

Zoho

https://www.zoho.com

RelateIQ

https://www.relateiq.com/

BambooHR

http://www.bamboohr.com/

6.薪水

Crunchbase

Wealthfront Startup Salary & Equity Compensation

https://www.wealthfront.com/tools/startup-salary-equity-compensation

AngelList Salary and Equity Data

https://angel.co/salaries

Salary.com

http://www.salary.com/

PayScale Salary Calculator

http://www.payscale.com/salary-calculator

CareerBuilder Salary Calculator

http://salary.careerbuilder.com/

Wolfram Alpha Salary Comparison

http://www.wolframalpha.com/examples/SalariesWages.html

PayScale Cost of Living Calculator

http://www.payscale.com/cost-of-living-calculator

CNN Money Cost of Living Calculator

http://money.cnn.com/calculator/pf/cost-of-living/

An Introduction to Stock & Options for the Tech Entrepreneur or Startup Employee

http://www.scribd.com/doc/55945011/An-Introduction-to-Stock-Options-for-the-Tech-Entrepreneur-or-Startup-Employee

Startup Equity for Employees

http://www.payne.org/index.php/Startup_Equity_For_Employees

An Engineer's Guide to Stock Options

http://blog.alexmaccaw.com/an-engineers-guide-to-stock-options

The Impact of Dilution

https://blog.wealthfront.com/impact-of-dilution/

Term Sheet: Liquidation Preference

http://www.feld.com/archives/2005/01/term-sheet-liquidation-preference.html

I have a job Offer at a startup, am I getting a good deal?

http://venturehacks.com/articles/job-Offer

The 14 Crucial Questions About Stock Options

https://blog.wealthfront.com/stock-options-14-crucial-questions/

How much are startup options worth?

http://www.danshapiro.com/blog/2010/11/how-much-are-startup-options-worth/

The Equity Equation

http://paulgraham.com/equity.html

How I negotiated my startup compensation

https://keen.io/blog/29904565692/how-i-negotiated-my-startup-compensation

[1] 这个表格主要是针对美国求职而言的。中国的程序员并不一定是这种形式,这里只是希望读者可以参考一下北美的面试流程。


本章主要介绍操作系统、文件系统相关的知识要点。大部分互联网公司的软件开发职位面试可能不会直接涉及这一层面的知识,但并不意味着这部分知识不重要。对于计算机底层实现的深入理解,能帮助你了解计算机的运行原理,能够更好地设计高效的架构,并且有助于调试、判断错误。特别地,对于多线程的理解尤为重要:现今的程序架构都需要并发处理,如何协调不同线程之间的分工协作,避免死锁、同步出错等问题,是程序员应当具备的技能。对于后端工程师而言,良好的操作系统知识基础更是深刻理解并实现复杂分布式系统的前提条件。

进程(process)与线程(thread)最大的区别是:进程拥有自己的地址空间,某进程内的线程对于其他进程不可见,即进程A不能通过传地址的方式直接读写进程B的存储区域。进程之间的通信需要通过进程间通信(Inter-Process Communication,IPC)。与之相对的,同一进程的各线程间之间可以直接通过传递地址或全局变量的方式传递信息。

此外,进程作为操作系统中拥有资源和独立调度的基本单位,可以拥有多个线程。通常操作系统中运行的一个程序就对应一个进程。在同一进程中,线程的切换不会引起进程切换。在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。相比进程切换,线程切换的开销要小很多。线程于进程相互结合能够提高系统的运行效率。

线程可以分为两类:

一类是用户级线程(user level thread)。对于这类线程,有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在。在应用程序启动后,操作系统分配给该程序一个进程号,以及其对应的内存空间等资源。应用程序通常先在一个线程中运行,该线程称为主线程。在其运行的某个时刻,可以通过调用线程库中的函数创建一个在相同进程中运行的新线程。 用户级线程的好处是非常高效,不需要进入内核空间,但并发效率不高。

另一类是内核级线程(kernel level thread)。对于这类线程,有关线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只能调用内核线程的接口。内核维护进程及其内部的每个线程,调度也由内核基于线程架构完成。内核级线程的好处是,内核可以将不同线程更好地分配到不同的CPU,以实现真正的并行计算。

事实上,在现代操作系统中,往往使用组合方式实现多线程,即线程创建完全在用户空间中完成,并且一个应用程序中的多个用户级线程被映射到一些内核级线程上,相当于是一种折中方案。

对于单核单线程CPU而言,在某一时刻只能执行一条CPU指令。上下文切换(Context Switch)是一种将CPU资源从一个进程分配给另一个进程的机制。从用户角度看,计算机能够并行运行多个进程,这恰恰是操作系统通过快速上下文切换造成的结果。在切换的过程中,操作系统需要先存储当前进程的状态(包括内存空间的指针,当前执行完的指令等等),再读入下一个进程的状态,然后执行此进程。

系统调用(System Call)是程序向系统内核请求服务的方式。可以包括硬件相关的服务(例如,访问硬盘等),或者创建新进程,调度其他进程等。系统调用是程序和操作系统之间的重要接口。

当用户创立多个线程/进程时,如果不同线程/进程同时读写相同的内容,则可能造成读写错误,或者数据不一致。此时,需要通过加锁的方式,控制核心区域(critical section)的访问权限。对于semaphore而言,在初始化变量的时候可以控制允许多少个线程/进程同时访问一个核心区域,其他的线程/进程会被堵塞,直到有人解锁。Mutex相当于只允许一个线程/进程访问的semaphore。此外,根据实际需要,人们还实现了一种读写锁(read-write lock),它允许同时存在多个读取者(reader),但任何时候至多只有一个写入者(writer),且不能与读取者共存。

在引入锁的同时,我们遇到了一个新的问题:死锁(Deadlock)。死锁是指两个或多个线程/进程之间相互阻塞,以至于任何一个都不能继续运行,因此也不能解锁其他线程/进程。例如,线程A占有lock A,并且尝试获取lock B;而线程2占有lock B,尝试获取lock A。此时,两者相互阻塞,都无法继续运行。

产生死锁的4个条件概括如下(只有当4个条件同时满足时才会产生死锁):

(1)Mutual Exclusion – Only one process may use a resource at a time

(2)Hold-and-Wait – Process holds resource while waiting for another

(3)No Preemption – Can’t take a resource away from a process

(4)Circular Wait – The waiting processes form a cycle

生产者消费者模型是一种常见的通信模型:生产者和消费者共享一个数据管道,生产者将数据写入buffer,消费者从另一头读取数据。对于数据管道,需要考虑为空和溢出的情况。同时,通常还需要将这部分共享内存用mutex加锁。在只有一个生产者一个消费者的情况下,可以设计无锁队列(lockless queue),线程安全地直接读写数据。

在介绍进程的时候,我们提起过一个进程不能直接读写另一个进程的数据,两者之间的通信需要通过进程间通信进行。进程通信的方式通常遵从生产者消费者模型,需要实现数据交换和同步两大功能。

(1)共享内存(Shared-memory)+ semaphore

不同进程通过读写操作系统中特殊的共享内存进行数据交换,进程之间用semaphore实现同步。

(2)信息传递(Message passing)

进程在操作系统内部注册一个端口,并且监测有没有数据,其他进程直接写数据到该端口。该通信方式更加接近于网络通信方式。事实上,网络通信也是一种IPC,只是进程分布在不同机器上而已。

所谓的逻辑地址,是指计算机用户(例如程序开发者)看到的地址。例如,当创建一个长度为100的整型数组时,操作系统返回一个逻辑上的连续空间:指针指向数组第一个元素的内存地址。由于整型元素的大小为4个字节,故第二个元素的地址时起始地址加4,以此类推。事实上,逻辑地址并不一定是元素存储的真实地址,即数组元素的物理地址(在内存条中所处的位置),物理地址并不是连续的,只不过操作系统通过地址映射,将逻辑地址映射成连续的,这样更符合人们的直观思维。

另一个重要概念是虚拟内存。操作系统读写内存的速度可以比读写磁盘的速度快几个量级。但是,内存价格也相对较高,不能大规模扩展。于是,操作系统可以将部分不太常用的数据移出内存,存放到价格相对较低的磁盘缓存,以实现内存扩展。操作系统还可以通过算法预测哪部分存储到磁盘缓存的数据需要进行读写,提前把这部分数据读回内存。虚拟内存空间相对磁盘而言要小很多,因此,即使搜索虚拟内存空间也比直接搜索磁盘要快。唯一慢于磁盘的可能是,内存、虚拟内存中都没有所需要的数据,最终还需要从硬盘中直接读取。这就是为什么内存和虚拟内存中需要存储会被重复读写的数据,否则就失去了缓存的意义。

现代计算机中有一个专门的转译缓冲区(Translation Lookaside Buffer,TLB),用来实现虚拟地址到物理地址的快速转换。

与内存/虚拟内存相关的还有以下两个概念:

(1)Resident Set

当一个进程在运行的时候,操作系统不会一次性加载进程的所有数据到内存,只会加载一部分正在用,以及预期要用的数据。其他数据可能存储在虚拟内存,交换区和硬盘文件系统上。被加载到内存的部分就是resident set。

(2)Thrashing

由于resident set包含预期要用的数据,理想情况下,进程运行过程中用到的数据都会逐步加载进resident set。但事实往往并非如此:每当需要的内存页面(page)不在resident set中时,操作系统必须从虚拟内存或硬盘中读数据,这个过程被称为内存页面错误(page faults)。当操作系统需要花费大量时间去处理页面错误的情况就是thrashing。

UNIX风格的文件系统利用树形结构管理文件。每个节点有多个指针,指向下一层节点或者文件的磁盘存储位置。文件节点还附有文件的操作信息(metadata),包括修改时间、访问权限等。

用户的访问权限通过访问控制表(Access Control List)和能力表(Capability List)实现。前者从文件角度出发,标注了每个用户可以对该文件进行何种操作。后者从用户角度出发,标注了某用户可以以什么权限操作哪些文件。

UNIX的文件权限分为读、写和执行,用户组分为文件拥有者、组和所有用户。可以通过命令对三组用户分别设置权限。

操作系统可以分为实时操作系统(Real-Time System),和分时操作系统(Sharing Time System)。通常计算机采用的是分时,即多个进程/用户之间共享CPU,从形势上实现多任务。各个用户/进程之间的调度并非精准度特别高,如果一个进程被锁住,可以给它分配更多的时间。而实时操作系统则不同,软件和硬件必须遵从严格的deadline,超过时限的进程可能直接被终止。在这样的操作系统中,每次加锁都需要仔细考虑。

对于高级语言来说,代码需要通过编译才能够运行。编译通过编译器(Compiler)实现,是一个将程序源代码转换成二进制机器码的过程。计算机可以直接执行二进制代码。在编译的过程中,编译器需要进行词法分析(Lexical Analysis)、解析(Parsing)和过渡代码生成(Intermediate Code Generation)。编译器的好坏可以直接影响最终代码的执行效率。


相关图书

递归算法与项目实战
递归算法与项目实战
群智能算法在人脑功能划分中的应用
群智能算法在人脑功能划分中的应用
数据结构抢分攻略  真题分类分级详解
数据结构抢分攻略 真题分类分级详解
量子计算:一种应用方法
量子计算:一种应用方法
数据结构与算法分析:C++语言描述(英文版·第4版)
数据结构与算法分析:C++语言描述(英文版·第4版)
数据分析的结构化表征学习
数据分析的结构化表征学习

相关文章

相关课程