几周前,我受邀在当地一所大学谈论并发。 本文总结了我在这里提出的内容。
![](https://i-blog.csdnimg.cn/blog_migrate/fca8dc9d9f1b2c1cbf365ce03a994955.png)
我们都在大学期间或以其他方式了解并行性/并发性。 任何学习编程的人都将不可避免地阅读/学习一些基本概念,例如,
- 线程,线程组,线程状态
- 种族条件,互斥,死锁,饥饿
- 锁,障碍,线程局部变量,原子变量
这个清单继续...
尽管并发是主流,但我们仍然发现很难处理。 为什么?
![](https://i-blog.csdnimg.cn/blog_migrate/cf2ab40515a21cc24449c530222585da.png)
一些观察:
- 关于并发的入门资料与现实世界中的并发/分布式应用程序之间存在很大的差距。
- 我们大多数人最终都没有遵循最佳实践。
- 应用教科书,介绍性内容(或从Web上剪切粘贴)来解决该问题。
那么最终结果是什么?
- 很多技术债务。
- 应用程序性能/稳定性差。
- 没有人理解代码! →很多不眠之夜/诅咒!
那么什么是解决方案?
由于过去的经验,我开始深入研究这个问题,显然我并不是唯一一个遭受痛苦的人。 互联网上有很多关于如何解决这个问题的文献。 这是一个摘要列表,谨记在心:
规则1:全局可变状态不好! (有或没有并发)
![](https://i-blog.csdnimg.cn/blog_migrate/38f849f1f5927eed2b92bd9e02254529.png)
注意:如果状态随时间变化,则任何事物都是可变的 ,否则不变。
例如,全局静态变量,带有公共实例变量的静态类,单例对象,环境变量,配置对象,集群应用程序中共享的数据/状态量。
随着应用程序规模和复杂性的增长(考虑程序中的多个活动部件,并且程序在集群环境中运行),拥有大量全局可变状态使得无法在给定时间预测程序的下一个状态,尤其是当您处于故障排除模式。 为了使事情变得更糟,您将无法控制状态更改。
现在我不会成为理想主义者,而是说我们将拥有一个零全球状态! 因为这不切实际。 但是可以说我们需要将其保持在最低水平。
规则2:使用应用程序框架-遵循其编程模型。
我们编写的大多数代码(=〜90%?)都是关于移动数据的,例如[获取数据→做某事→在GUI中显示或放入存储中]。 这意味着我们无需处理,实际上不必直接处理并发。 除非我们正在编写一些特殊目的的代码,例如编写我们自己的框架/服务器运行时。
每种编程语言和周围的生态系统都提供更高级别的并发控制结构,因此我们大多数人不需要手动创建线程(同步块/锁等)。 这些范例中的大多数提供了基于组件的简单编程模型(例如,J2EE / Spring中的Bean,Servlet,控制器),使应用程序程序员可以将重点放在业务逻辑上而不是样板代码上。
因此,每次我们想引入线程/同步块时,退后一步并合理化需求总是一个好主意。
规则3-最佳做法
其中大多数只是显而易见的,并在更广泛的软件工程意义上应用。 我并不是要提供详尽的清单。 但是请发表评论,如果我错过了这里需要做的任何事情!
- 减少对全局变量/数据的使用:使用正确的范围。 如果应用程序以该模式运行,则这需要在应用程序级别以及整个集群上发生。 这包括正确定义应用程序中的组件/层以及如何在每个相邻层之间交换数据/状态。
- 最小化锁定范围 :不要滥用同步,我遇到了很多情况,在这种情况下,我们倾向于默认使用此方法来修复与并发相关的问题。 更多同步意味着性能降低的可能性更大。
- 线程池:这是显而易见的。 创建线程需要大量的样板工作(以及运行时开销)。 如果有人愿意这样做,他/她将活在过去并试图重新发明轮子。
- 使用更高层次的结构:我们中的一些人可能会不同意,但是我遇到的大多数数据共享需求都映射到消费者-生产者模式(及其变体)。 任何编程语言都应该通过并发包来支持。 为什么不使用它(例如,在Java中为java.util.concurrent.BlockingQueue的子类)。 还可以选择更复杂的替代方法,例如LMax Disruptor(Java中),Reactive编程(例如RxJava,Akka,Spring Reactor)。
- 线程体系结构:并发不是我们以后要弄清楚/设计的一个方面。 考虑以下几点:
数据访问模式(例如,计算繁重/ IO繁重)
部署(例如VM环境,容器,工业计算机)硬件/资源约束
错误处理/跟踪/调试。
结论
- 当我们缺乏“工作知识”并且没有遵循最佳实践时,处理并发就变得很困难。
- 应用程序中过多的全局可变状态是有问题的。
- 与使用裸机相比,更喜欢使用更高级别的并发控制构造(/框架)。
- 预先选择/设计线程架构很重要。
滑轨:
https://www.slideshare.net/ramithj/concurrency-why-its-hard-126939361
参考文献:
- https://smartbear.com/blog/test-and-monitor/why-johnny-cant-write-multithreaded-programs/
- https://towardsdatascience.com/is-concurrency-really-increases-the-performance-8cd06dd762f6
- https://www.quora.com/What-are-some-good-and-bad-use-cases-for-concurrency-models-like-threading-actors-and-STM-Software-Transactional-Memory-When-我应该选择另一个
- https://joearms.github.io/published/2016-01-26-The-Unintentional-Side-Effects-of-a-Bad-Concurrency-Model.html
- 并发-好的,坏的,丑陋的-https: //www.youtube.com/watch?v= OJfS7K- Vkgk
- https://javarevisited.blogspot.com/2015/05/top-10-java-multithreading-and.html
- https://www.youtube.com/watch?v=OJfS7K-Vkgk
From: https://hackernoon.com/why-concurrency-is-hard-a45295e96114