史上最全的 Java 并发系列之并发编程的挑战
前言
文本已收录至我的 GitHub 仓库,欢迎 Star:https://github.com/bin392328206/six-finger
种一棵树最好的时间是十年前,其次是现在
我知道很多人不玩 qq 了,但是怀旧一下,欢迎加入六脉神剑 Java 菜鸟学习群,群聊号码:549684836 鼓励大家在技术的路上写博客
絮叨
从今天开始,我们进入一个新的领域学习,这个领域的学习,我打算跟着 Java 并发编程的艺术走,整本书是十一章,意味着我会写十篇左右博客在 Java 并发系列中,我希望通过我对这本书的总结,能让大家在面试和实际工作中运用上 Java 的并发知识
Java 并发编程的艺术
这本书还算可以吧,毕竟是阿里专家写的,然后我其实很早就买了,但是没怎么看,刚好因为大家喜欢我的文章,那我就很有动力去学习,然后把学到的知识分享给大家,
总共的章节有
并发编程的挑战
Java 并发机制的底层实现
Java 内存模型
Java 并发编程基础
Java 中的锁
Java 并发容器和框架(前面讲 Java 容器提到过)
Java 中的 13 个原子类
Java 中并发的工具类
Java 中的线程池
Executor 框架
实战(这个是案例)
JUC
这个肯定要知道是啥的,它是 Java JDK 中的一个安全包,别等面试官问你有没有接触过 JUC,你连听都没有听到过,就尴尬了。
在 Java 5.0 提供了 java.util.concurrent(简称 JUC)包,在此包中增加了在并发编程中很常用的工具类,用于定义类似于线程的自定义子系统,包括线程池,异步 IO 和轻量级任务框架;还提供了设计用于多线程上下文中的 Collection 实现等;
其实我们要讲的并发系列,也就是讲上图的内容来的。
并发编程的目的与挑战
并发编程的目的是为了让程序运行得更快。启动更多的线程并不一定就能让程序最大限度地并发执行。
希望通过多线程执行任务让程序运行得更快,会面临非常多的挑战。比如
上下文切换 的问题
死锁 的问题
硬件和软件的资源限制问题
上下文切换
单核处理器也支持多线程执行代码,CPU 通过给每个线程分配 CPU 时间片来实现这个机制。时间片是 CPU 分配给各个线程的时间,因为时间片非常短,所以 CPU 通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。
CPU 通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。
这个的意思就是告诉我们,并不是说线程越多越好,因为每个线程的使用 cpu 的时间是根据算法算出来的,也差不多算平均吧,如果你的线程太多,但是有很多线程是空闲状态,那你们你上下文切换的时间就是浪费的,这样还不如单线程执行呢,还有就是执行的次数,如果执行的次数少,那么串行也会比较快,有实验证明在 10W 循环执行中,2 者的速度差不多
我们如何去减少上下文的切换
减少上下文切换的方法有 无锁并发编程、CAS 算法、使用最少线程 和 使用协程。
无锁并发编程。多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的 ID 按照 Hash 算法取模分段,不同的线程处理不同段的数据。
CAS 算法。Java 的 Atomic 包使用 CAS 算法来更新数据,而不需要加锁。
使用最少线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态。
协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。
死锁
所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。 因此我们举个例子来描述,如果此时有一个线程 A,按照先锁 a 再获得锁 b 的的顺序获得锁,而在此同时又有另外一个线程 B,按照先锁 b 再锁 a 的顺序获得锁。如下图所示:
死锁产生的 4 个必要条件?
互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。
预防死锁:
避免一个线程同时获取多个锁。
避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
尝试使用定时锁,使用 lock.tryLock(timeout)来替代使用内部锁机制。(锁超时)
对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
资源限制的挑战
硬件资源限制有带宽的上传/下载速度、硬盘读写速度和 CPU 的处理速度。
软件资源限制有数据库的连接数和 socket 连接数等。
如何解决资源限制的问题
对于硬件资源限制,可以考虑使用集群并行执行程序。比如使用 ODPS、Hadoop 或者自己搭建服务器集群,要么用阿里云的服务。
对于软件资源限制,可以考虑使用资源池将资源复用。比如使用连接池将数据库和 Socket 连接复用,或者在调用对方 webservice 接口获取数据时,只建立一个连接。
本章总结
作者的建议是使用 JDK 并发包下的容器和工具类来解决并发问题,因为这些是已经经过了大量的测试,可以解决前面提到的几个挑战
结尾
第一章 介绍了并发的目的,和挑战,从全局大观上知道我们要学习的一个方向,继续加油吧。
因为博主也是一个开发萌新 我也是一边学一边写 我有个目标就是一周 二到三篇 希望能坚持个一年吧 希望各位大佬多提意见,让我多学习,一起进步。
日常求赞
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是神人。
创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见
六脉神剑 | 文 【原创】如果本篇博客有任何错误,请批评指教,不胜感激 !
版权声明: 本文为 InfoQ 作者【自然】的原创文章。
原文链接:【http://xie.infoq.cn/article/c9118c8f29400d2d9f36f06a9】。文章转载请联系作者。
评论