前言:多线程是程序员必须掌握的一项基础知识,可是因为各类框架封装使得咱们平时不多能接触到多线程。一旦项目中发生问题,便无从下手。学会了多线程不只能帮助你更好地处理项目中的问题,还能对你理解一些框架有所帮助。本系列以《Java并发编程的艺术》为参考,结合网上的一些资料并结合本身的理解整理而成。若有错误,欢迎指正。 程序员
一、几个概念算法
1)进程:是具备必定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的独立单位。一个操做系统中能够同时运行多个任务(程序),每一个运行的任务(程序)被称为一个进程。例如,启动一个Java程序,操做系统就会建立一个Java进程。数据库
2)线程:它是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),可是它能够与其它同属一个进程的其余线程共享进程所拥有的所有资源。编程
3)上线文切换:服务器
即便单核处理器也支持多线程执行代码,CPU经过给每一个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,由于时间片很是短,因此CPU经过不停地切换线程执行,让咱们感受多个线程是同时执行的。多线程
CPU经过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。可是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,能够再加载这个任务的状态。因此任务从保存到再加载的过程就是一次上下文切换。并发
这就比如咱们同时读两本书,当在读一本英文的技术书时,发现某个单词不认识,因而便打开字典查找,可是查找以前必须先记住这本书已经读到了多少页的多少行。等查完单词之后,可以继续读这本书。这样的切换是会影响读书效率的,一样上下文切换也会影响多线程的执行效率。框架
2.为何要使用多线程?工具
1)充分利用系统资源性能
因为摩尔定律周期愈来愈长,处理器性能的提高方式也从更高的主频向多核发展。线程是大多数操做系统调度的基本单元,而线程是进程的一个实体。一个线程同一时刻只能运行在一个cpu上,这样就没法充分利用系统资源。若是将计算任务分配给多个处理器核上,就会显著减小程序的处理时间。
2)更快地响应时间
例如,在一些复杂的业务中,用户从点击按钮开始,服务端须要进行一系列处理过程才能将最终的结果返回给客户端。使用多线程技术,能够将实时性要求高的数据处理完成之后即将执行结果返回到客户端。而一些数据一致性不强的操做派发给其它线程处理(如消息队列/Worker)。这样能够缩短响应时间,提高了用户体验。
3)更好的编程模型
Java为多线程提供了良好的、考究而且一致的编程模型,使得开发人员更加专一于问题的解决。某些类型的问题,例如仿真,没有并发是很难解决的。大多数人都看到过至少一种形式的仿真,例如计算机游戏中或电影中计算机生成的动画。完整的仿真一般涉及许多交互式元素,每个都有本身的“想法”。从编程角度看,模拟每一个仿真元素都是独立的任务----好比游戏中的门与岩石,或者精灵与巫师。(详细可参考Tink in Java第四版 21.1.2小节)
3.多线程面临的问题
在并发编程中,须要解决的两个问题:线程之间如何通讯以及线程之间如何同步。通讯是指线程之间以何种机制来交换信息,同步是指程序中用于控制不一样线程间相对执行顺序的机制。
1)线程间的通讯机制有两种:共享内存和消息传递。
共享内存的并发模型中,线程之间共享程序的公共状态,经过写-读内存中的公共状态进行隐式通讯。在消息传递的并发模型里,线程之间没有公共状态,线程间的通讯必须经过发送消息来进行显示通讯(好比Java中Object对象的wait()与notify())。
2)同步机制
在并发编程中,尤为是在处理共享资源时,须要将某些操做(例如写操做)转化为同步,以避免形成不可思议的后果。常见的同步机制有如下两种:JVM层面,借助Object的monitor实现(synchronized);经过总线锁或者锁定内存部分区域实现,例如volatile。
四、并发编程挑战
1)上下文切换。
当线程较多时,频繁的上线文切换会致使执行效率下降,合理地调整线程数能够将并发执行效率最大化。
2)死锁。
锁是很是有用的工具,运用场景很是多。可是若是使用不当可能会带来死锁问题,严重时可能使系统瘫痪。死锁即建立两个线程A和B,A拥有锁a,同时须要获取锁b,而B拥有锁b,同时须要获取锁a。二者均持有锁,没法获取所需锁。在实际开发中,要避免死锁的产生。
避免死锁的常见方法
a.避免一个线程同时获取多个锁
b.便面一个线程在锁内同时占用多个资源,尽可能保证每一个锁只占用一个资源。
c.尝试使用定时锁,使用lock.tryLock(timeout)
d.对程序进行异常处理,保证程序发生异常时锁能够正常释放。
d.对于数据库锁,加锁和解锁必须在同一个数据库链接里,不然会出现解锁失败问题。
3)资源限制。
资源限制指在并发编程中,受限于计算机硬件资源或软件资源。例如,一个服务器的贷款只有2M/s,当使用多线程时,并不会提升下载速度。由于受限于资源,线程仍然是串行执行。程序反而会更慢,因为上下文切换和资源调度时间。
对于硬件资源,能够经过增长带宽或者增长集群方式解决。对于软件资源,例如数据库链接,能够经过控制线程并发数来使得资源利用率最大化。