高手问答第 288 期 —— 带你深入理解高并发编程

OSC哒哒 发布于 2022/07/26 18:09
阅读 7K+
收藏 14

【开源中国 APP 全新上线】“动弹” 回归、集成大模型对话、畅读技术报告”

随着互联网的不断发展,CPU硬件的核心数也在不断提升,并发编程越来越普及,但是并发编程并不像其他业务那样简单明了。在编写并发程序时,往往会出现各种各样的Bug,这些Bug常常以某种“诡异”的形式出现,然后迅速消失,并且在大部分场景下难以复现。所以,高并发编程着实是一项让程序员头疼的技术。

OSCHINA本期高手问答( 727日-82日) 我们请来了 @冰-河 和大家一起探讨关于高并发编程相关的问题。

可讨论的问题包括但不限于:

  1. 为什么需要学习并发编程?
  2. 并发编程需要掌握的基础与核心知识
  3. 并发编程存在哪些风险
  4. 并发编程的本质问题
  5. 并发编程的那些坑

或者其它关于并发编程、分布式系统、架构的相关问题,也欢迎大家积极提问!

嘉宾介绍

冰河,互联网资深技术专家、MySQL 技术专家、分布式与微服务架构专家。

多年来一直致力于分布式系统架构、微服务、分布式数据库、分布式事务与大数据技术的研究,在高并发、高可用、高可扩展性、高可维护性和大数据等领域拥有丰富的架构经验。

可视化多数据源数据异构中间件 mykit-data 作者,深入理解高并发编程作者,“冰河技术”微信公众号作者。

为了鼓励踊跃提问,@博文视点  会在问答结束后从提问者中抽取 5 名幸运会员赠予《深入理解高并发编程:核心原理与案例实战》一书。

京东5折购买链接:https://u.jd.com/ftfvdgr

OSChina 高手问答一贯的风格,不欢迎任何与主题无关的讨论和喷子。

下面欢迎大家就高并发编程关问题向 @冰-河 提问,请直接回帖提问~

加载中
0
yaosaya
yaosaya

高手问答第 288 期 —— 带你深入理解高并发编程

@feelings777 @Mark哥是我 @pyboy58 @dwingo @web实习虫

恭喜以上5位网友分别获得《深入理解高并发编程:核心原理与案例实战》书籍一本

请于8月12日前登陆账号, 私信 @yaosaya  告知快递信息(格式:姓名+电话+地址)

南方Go
南方Go
这本书要拿到公司天天看
1
enable-
enable-

@冰-河 大佬 你好 问几个问题咨询下您

  1. 通俗易懂的讲讲 并发编程 中的 并发模型, 并发时候锁处理 相关,例如 Clojure 中的巧妙并发
  2.  对于 分布式系统中的难以逾越的三座大山:NPC。N:Network Delay,网络延迟P:Process Pause,进程暂停C:Clock Drift,时钟漂移  你有什么 好的 理解 或解决方案呢。
  3. 并发编程 需要注意哪些潜在的坑呢,比如涉及到线程通讯,缓存可见,编译优化,以及原子性
冰-河
冰-河
回复 @冰-河 : 这里也可以列举一些并发编程中需要注意的坑:SimpleDateFormat不是线程安全的、死锁、自旋锁造成CPU 100%,ThreadLocal内存溢出等等。
冰-河
冰-河
关于第三个问题:并发编程中需要注意线程之前的分工、同步和互斥问题,造成并发编程容易出现问题的根源,原子性、可见性和有序性问题。这些问题在《深入理解高并发编程:核心原理与案例实战》一书中都有详细的讲解。
冰-河
冰-河
回复 @冰-河 : 说的具体一点,NPC对分布式系统造成的一个典型影响就是数据的一致性问题,也就是说,在分布式系统中,追求高性能的同时,很难做到数据的强一致性,那我们是不是可以做到弱一致性或者最终一致性呢?在研发分布式系统时,更多的是需要根据某些场景做取舍与平衡。
冰-河
冰-河
关于第2个问题:在分布式系统中,NPC问题一直是比较难解决的问题,除了分布式系统本身的复杂性外,还有很多外界因素导致分布式系统的复杂性再度提升,目前,业界还没有一种完美的解决方案能够解决分布式系统的所有问题。我们在设计或研发分布式系统的过程中,需要针对这些问题,做好取舍。例如,NPC问题在分布式系统中是无法避免的,那我们是不是有什么方案尽量降低其对分布式系统的影响呢?
冰-河
冰-河
你好,关于第1个问题:并发模型大体上可以归为量大类:共享内存模式和消息通信(也可以叫做消息传递模型)。共享内存模型可以在内存中通过读写共享变量实现,Java中的并发编程主要使用的就是共享内存模型。消息传递模型可以通过消息通道发送消息实现,消息通道可以通过网络连接不同的服务器。
1
dwingo
dwingo

@冰-河 请问, 如何看待协程在各种编程语言中逐渐流行, Java也开始支持类似的虚拟线程, 这些机制能否简化高并发编程呢?

dwingo
dwingo
回复 @freekevin : jdk19的虚拟线程我试用过了, 效果还可以, 用在不方便写异步且并发量很大的场合, 但目前也不是很完善, 调度器还没放开自定义, synchronize仍然会锁住线程, netty最新版为此还改用lock重构了. 希望下个LTS版本的JDK21能稳定用上.
freekevin
freekevin
jdk19也还计划那 java这波有点慢了
冰-河
冰-河
在一定程度上可以简化,也可以进一步提升并发编程的性能,例如协程可以做到CPU不用在内核态与用户态之间切换
1
Mark哥是我
Mark哥是我

谢谢冰河大佬发布的很多免费的技术文档,对于并发编程,我有几个问题请教。

  1. Java当前的主流并发仍然是线程,但是Kotlin的协程,以及JDK19的VirtualThread陆续引入,这些更加轻量级的并发调度的引入对当前基于线程的调度会产生哪些影响?
  2. 我看码云前几天发布的《Netty 5.0.0.Alpha4 发布》的文章中的更新日志中有提到:"用 java Locks 替代 synchronized,以更好地支持 Loom",这样看来 synchronized 关键字不能在协程中调度了?
  3. 线程数量的设置,有不少说法,比如计算型任务的最大数量是N+1,核心是多少之类的。IO型的任务又是一个什么公式。我觉得都是太理想化了,因为服务器资源通常又不是只跑一个应用,那么这个线程核心数量和最大数量的有推荐的设置方式吗?
  4. Tomcat的线程池调度和JDK的线程池调度不一样,Tomcat是优先分配的临时线程,JDK是积压到队列,这二者分开设计的原因是什么?我的看法是因为Tomcat处理的是Web请求,都是IO处理对CPU要求少,能保证CPU不被压榨,但是JDK的线程池任务类型不明确,所以为了稳定,采用的是比较保守的方式,不知道冰河怎么看(除了眼睛😀)?
冰-河
冰-河
关于第4个问题,在一定程度上可以这么理解。
冰-河
冰-河
关于第3个问题,可以根据系统是CPU密集型还是I/O密集型进行确定,然后根据不断压测得出最终的结果。当然也有一些经验值,在《深入理解高并发编程:核心原理与案例实战》一书中有详细的描述。
冰-河
冰-河
关于第2个问题,synchronized涉及到锁升级的问题,一旦升级到重量级锁,会涉及到CPU内核态与用户态的切换问题,协程主要是在用户态工作。所以, java Locks在某些场景下比synchronized能够更好的支持Loom。
冰-河
冰-河
关于第1个问题,这些技术的引入一方面会使并发编程变得越来越轻量,在一定程度上能够简化并发编程的复杂性,另一方面也可以提升并发编程的性能。
1
赤脚小子
赤脚小子

@冰-河 你好,

1.  高并发下mysql主从延迟严重,如何解决呢?

2. 并发在JAVA可以显式使用线程池或者stream fork/join隐式去做,能说下二者分别适合什么样的场景么?

3. 并发就可能涉及到同步代码块,现在流行的说法是synchronized关键字在JDK8已经得到了足够的优化,基本不用lock级别的代码了,请问是这样么?

4. JAVA并发编程有个问题是需要第三方TransmittableThreadLocal这样的工具才能实现一些场景,jdk的作者们都是大神,为什么没考虑到这样的场景呢?

冰-河
冰-河
关于第4个问题,我的理解是:ThreadLocal在JDK1.2就已经存在了,其实像TransmittableThreadLocal这些类都是在具体的业务场景下使用JDK中的类库出现某种问题的情况下,不断优化从而开发出来的,JDK的作者们可能没在这些场景下出现这些问题吧,毕竟每个人精力有限,不可能经历所有的业务场景。
冰-河
冰-河
关于第3个问题,synchronized确实做了很多优化处理,在性能上几乎与Lock锁相差不大。但是在使用上可以根据具体场景确定使用哪种锁。
冰-河
冰-河
关于第2个问题,线程池可以使用在需要创建大量线程异步执行任务,但为了防止无限制创建线程对系统造成的影响,同时便于线程复用和管理的场景,fork/join适合使用在能够将一个大任务拆分成多个同种类型的小任务进行处理,最终将处理结果合并的场景,有点类似于Hadoop的MapReduce,关于Hadoop或者其他的大数据技术,可以参考我出版的《海量数据处理与大数据技术实战》一书。
冰-河
冰-河
关于第1个问题,MySQL主从延迟严重,可以尝试下并行复制,这个在我出版的《MySQL技术大全:开发、优化与运维实战》一书中有详细的讲解。
0
KelvinQ
KelvinQ

@冰-河 高并发虽好,但一定会引入很多“高危险”的隐患,请问大佬如何设计才能更好的平衡软件复杂性和性能的问题?

冰-河
冰-河
你好,其实系统的架构设计都是根据具体的业务场景进行设定的,虽然业界有一些通用的解决方案,但是这些方案更多的是给出一个通用化的模型,如果使用到自己的业务场景下,还是需要根据具体的业务场景进行评估。关于如何更好的平衡软件的复杂性和性能,目前没有一个完美的解决方案,而是需要结合具体的业务场景进行深入分析,做出取舍。
0
e
ericyan1

@冰-河   请问, 并发编程 试用哪些场景呢? 不适合哪些场景呢?

冰-河
冰-河
从广义上来说,目前的系统大部分都采用的并发编程,并发编程使用的场景也非常丰富,例如:定时任务、系统监听、日志收集、大数据处理等等
0
凌小宇
凌小宇

@冰-河  请问大佬们都是怎么处理并发导致的一致性问题呢

冰-河
冰-河
并发编程下确实很容易出现数据的一致性问题,此时我们需要根据具体的业务场景使用一些并发编程技巧来尽量解决问题,例如,加锁、volatile、内存屏障等等,当然使用哪种方案还是根据业务场景而定。《深入理解高并发编程:核心原理与案例实战》一书都对这些技术方案有详细的描述。
0
忘了名字
忘了名字

@冰-河 老师能说下 开启线程时 初始化线程上下文 的过程和资源消耗吗 怎么判断串行和开启线上的资源权衡

0
empireghost
empireghost

@冰-河   

  • 并发编程存在哪些风险?
  • 并发编程的那些坑?
  • 感觉并发编程技术技巧都是针对单 JVM的环境的,
  • 现在一般都是分布式环境,怎么应对这种情况?
冰-河
冰-河
关于前两个问题在《深入理解高并发编程:核心原理与案例实战》一书中有详细的描述。另外,并发编程不只是单机环境,在分布式环境下的很多场景也是需要并发编程的,例如大数据处理,分布式锁、异步并行处理等等都是在分布式环境下的并发编程的体现。
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部