Java并发编程 • 基础 • 初识

一直以来对并发编程都停留在模糊的概念记忆,不曾全面学习、深刻理解,遂读一本好书,深刻理解,实践体会。

并发编程的粒度是线程,线程也是现代操作系统的最基本调度单元,那么多线程的出现缘由是什么呢?
从历史的角度看

操作系统出现之前:在裸机上只能有一个程序运行从头到尾地执行 。

操作系统出现之后:在操作系统上可以有多个程序(即:进程)运行,并在进程间提供了交互机制(例如:同一台机器上客户端程序和服务器程序进行socket通信),提高了资源利用率,以及增加了程序间的交互。

然而,在支持线程的操作系统出现之前,程序是以一种串行模式执行的指令。以现实中的场景为例,起床,洗漱,烧水,等水开,煮咖啡。为什么不在等水开的过程中去做点别的事?比如看书、整理房间等,这样时间利用率岂不是更高。引申到程序中,为什么不在程序进行使用IO读取文件的过程中去利用CPU进行接下来的计算工作呢?考虑到串行模式的程序在同一时间内只会使用计算机中的某一种资源,并且在这个过程中会发生等待,结果,以线程为基本调度单元的操作系统出现了,自然,并发编程也应运而生。

多线程的优势
  1. 提高了资源利用率,特别是在多核处理器普及的今天,单线程程序跑在多个处理器上,根本无法体现多核的优势;
  2. 建模更加简单,多线程模型更加符合人类的思维习惯;
  3. 程序更易于开发、维护,根据单一职责模式,一段程序做一件事比一整个程序做多件事更容易开发,更易于维护;
  4. 改善了程序的用户交互性,例如UI交互,部分操作不需要等待后台处理完才返回,提高及时性;
  5. 简化了异步事件,单线程中一旦IO阻塞,则整个程序阻塞,多线程则可以继续下面的流程;
多线程的风险

多线程带来了一系列资源上,开发上以及产品上的好处,自然也提高了对开发者的要求。

安全性问题:

  1. 由于线程共享进程内资源,当多个线程在同一段时间访问、修改同一个变量,结果将变得不可预测,如下A、B线程,value在经过两次+1之后本是11,却因为执行顺序的原因,导致错误的结果;
  2. 在编译,运行的过程中,编辑器,JVM,硬件都可能会对程序指令重排,程序的执行顺序将不可预测;
A 线程:value=9  --->  value+1  --->  value=10  
B 线程:  ---> value=9  --->  value+1  --->  value=10 
复制代码

活跃性问题:

  1. 程序可能因为不正确的执行顺序导致无限循环,资源不释放,死锁等问题;

性能问题:

  1. 多线程在并发运行时需要CPU的调度,当从一个线程切换到另一个线程时,需要保存上一个线程的相关运行环境,并在重新运行> 时恢复它的运行环境,频繁的线程切换导致CPU的资源集中在切换上下文环境上,而不是业务逻辑,造成了巨大的额外开销;
  2. 数据共享、同步机制会抑制编译器,以及操作系统对程序执行的优化,例如,内存缓存区的数据将变得无效;
多线程无处不在

初学者一般不考虑多线程问题,或者因为害怕线程问题而不曾在企业级代码中显示地创建线程,但是多线程依然无处不在。

JVM在启动时,会创建一些后台线程,例如垃圾回收器,并启动一个线程执行main方法。

最常见的使用框架(例如 spring)进行web开发,客户端发出请求,服务器接收请求并执行业务逻辑。在这过程中,框架已经为当前的请求创建了一个线程,并在这个线程中执行业务逻辑。如果在程序中访问共享可变的对象,那么就可能会发生并发问题,框架将并发问题带入了程序中。

转载于:https://juejin.im/post/5c4c0afc51882525a72453ee

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值