You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
8.1 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 开篇词 | 你为什么需要学习并发编程?
你好我是王宝令资深架构师目前从事电商架构的设计工作。从毕业到现在我前前后后写了15年的程序刚毕业的时候从事证券业务的开发开发语言是C/C++之后从事ERP产品的研发开发语言主要是C#和Java最近几年主要是从事Java开发平台和基础中间件的设计开发工作。
还记得毕业后我接触的第一个项目是证券相关的国外的同事用C语言写了一个内存数据库代码写得极为简练优美我当时怀着无比崇敬的心情把代码看了又看看完感觉受益匪浅。不过兴奋之余我也有些焦虑因为其中一块并发相关的代码我看得是云里雾里总感觉自己没有悟透。
我下意识地告诉自己说这块的知识积累还不够所以要勤学苦练。你可知道15年前相关的学习资料并不多我的师傅向我推荐了《操作系统原理》这本教材他说“并发编程最早的应用领域就是操作系统的实现你把这本书看懂了并发的问题自然就解决了。”但是理论和实践之间总是有鸿沟的之后好多年最让我感到无助的还是处理并发相关的问题。
并发编程的掌握过程并不容易。我相信为了解决这个问题你也听别人总结过并发编程的第一原则那就是不要写并发程序。这个原则在我刚毕业的那几年曾经是行得通的那个时候多核服务器还是一种奢侈品系统的并发量也很低借助数据库和类似Tomcat这种中间件我们基本上不用写并发程序。或者说并发问题基本上都被中间件和数据库解决了。
**但是最近几年,并发编程已经慢慢成为一项必备技能。**
这主要是硬件的驱动以及国内互联网行业的飞速发展决定的现在64核的服务器已经飞入寻常百姓家大型互联网厂商的系统并发量轻松过百万传统的中间件和数据库已经不能为我们遮风挡雨反而成了瓶颈所在。
于是,并发编程最近几年成为非常热门的领域,人才稀缺。但与此同时,关于并发编程的书籍也渐渐丰富起来了。所以当极客时间团队和我聊这个专栏的时候,我的第一个疑问就是目前市面上已经有很多这方面的图书了,而且很多都非常优秀,是否还有必要搞一个这样的专栏。
但是深入想过之后,我坚定了写作的信心。这些年接触的大部分同学,都是工作几年后很多技术突飞猛进,却只有并发编程成为瓶颈,虽然并发相关的类库他们也熟悉,却总是写不出正确、高效的并发程序,原因在哪里?我发现很多人是因为某个地方有了盲点,忽略了一些细节,但恰恰是这些细节决定了程序的正确性和效率。
而这个盲点有时候涉及对操作系统的理解,有时候又涉及一点硬件知识,非常复杂,如果要推荐相关图书,可能要推荐好几本,这就有点“大炮打蚊子”的感觉了,效率很差。同时图书更追求严谨性,却也因此失掉了形象性,所以阅读的过程也确实有点艰辛。
**我想,如果能够把这些问题解决,那么做这个事情应该是有意义的。**
例如Java里synchronized、wait()/notify()相关的知识很琐碎看懂难会用更难。但实际上synchronized、wait()、notify()不过是操作系统领域里管程模型的一种实现而已Java SDK并发包里的条件变量Condition也是管程里的概念synchronized、wait()/notify()、条件变量这些知识如果单独理解,自然是管中窥豹。但是如果站在管程这个理论模型的高度,你就会发现这些知识原来这么简单,同时用起来也就得心应手了。
管程作为一种解决并发问题的模型是继信号量模型之后的一项重大创新它与信号量在逻辑上是等价的可以用管程实现信号量也可以用信号量实现管程但是相比之下管程更易用。而且很多编程语言都支持管程搞懂管程对学习其他很多语言的并发编程有很大帮助。然而很多人急于学习Java并发编程技术却忽略了技术背后的理论和模型而理论和模型却往往比具体的技术更为重要。
此外Java经过这些年的发展Java SDK并发包提供了非常丰富的功能对于初学者来说可谓是眼花缭乱好多人觉得无从下手。但是Java SDK并发包乃是并发大师Doug Lea出品堪称经典它内部一定是有章可循的。那它的章法在哪里呢
**其实并发编程可以总结为三个核心问题:分工、同步、互斥。**
所谓**分工**指的是如何高效地拆解任务并分配给线程,而**同步**指的是线程之间如何协作,**互斥**则是保证同一时刻只允许一个线程访问共享资源。Java SDK并发包很大部分内容都是按照这三个维度组织的例如Fork/Join框架就是一种分工模式CountDownLatch就是一种典型的同步方式而可重入锁则是一种互斥手段。
当把并发编程核心的问题搞清楚再回过头来看Java SDK并发包你会感觉豁然开朗它不过是针对并发问题开发出来的工具而已此时的SDK并发包可以任你“盘”了。
而且这三个核心问题是跨语言的你如果要学习其他语言的并发编程类库完全可以顺着这三个问题按图索骥。Java SDK并发包其余的一部分则是并发容器和原子类这些比较容易理解属于辅助工具其他语言里基本都能找到对应的。
**所以,你说并发编程难学吗?**
首先难是肯定的。因为这其中涉及操作系统、CPU、内存等等多方面的知识如果你缺少某一块那理解起来自然困难。其次难不难学也可能因人而异就我的经验来看很多人在学习并发编程的时候总是喜欢从点出发希望能从点里找到规律或者本质最后却把自己绕晕了。
我前面说过并发编程并不是Java特有的语言特性它是一个通用且早已成熟的领域。Java只是根据自身情况做了实现罢了当你理解或学习并发编程的时候如果能够站在较高层面系统且有体系地思考问题那就会容易很多。
所以我希望这个专栏更多地谈及问题背后的本质、问题的起源同时站在理论、模型的角度讲解Java并发让你的知识更成体系融会贯通。最终让你能够得心应手地解决各种并发难题同时将这些知识用于其他编程语言让你的一分辛劳三分收获。
下面就是这个专栏的目录,你可以快速了解下整个专栏的知识结构体系。
![](https://static001.geekbang.org/resource/image/d5/c0/d513beec13a20d5e858257313b3605c0.jpg)
**当然,我们要坚持下去,不能三天打鱼两天晒网,因为滴水穿石非一日之功。**
很多人都说学习是反人性的,开始容易,但是长久的坚持却很难。这个我也认同,我面试的时候,就经常问候选人一个问题:“工作中,有没有一件事你自己坚持了很久,并且从中获益?”如果候选人能够回答出来,那会是整个面试的加分项,因为我觉得,坚持真是一个可贵的品质,一件事情,有的人三分热度,而有的人,一做就能做一年,或者更久。你放长到时间的维度里看,这两种人,最后的成就绝对是指数级的差距。
我希望你能和我坚持下来,我们一起学习,一起交流,遇到问题不是简单地抱怨和逃避,而是努力探寻答案与解决方法。这一次,就让我们一起来坚持探索并发编程的奥秘,体会探索知识的乐趣。今天的文章是开篇词,我们的主菜很快就来,如果可以的话,还请在留言区中做个自我介绍,和我聊聊你目前的工作、学习情况,以及你在并发编程方面的学习痛点,方便我在后面针对性地给你讲解,这样,我们可以彼此了解。
最后,感谢你对我的信任,我定会努力实现完美交付。