一.初识Java并发编程

一.初识Java并发编程

一.什么是并发编程

​ 在程序中,有很多耗时但又不占用CPU的任务(比如输入输出),如果采用用串行的方式运行程序,那么CPU绝大部分的时间都是空闲的.CPU通过给每个线程分配时间片,让各个线程间断执行,以此来充分利用CPU.因为时间片非常短,让我们感觉这些任务是同时执行的,所以叫并发执行.(需要注意,这里的并发实际上每个瞬间只有一个线程在运行)

​ 并发编程是为了提高CPU效率而设计的,那么并发编程一定快么?
在这里插入图片描述
上图是一个累加程序运行时间分析,由表可知,当累加的次数大于1百万时,并发的效率明显高于串行执行,反则亦然.这是因为,使用并发编程时,需要考虑到线程切换的成本:上下文切换.

二.上下文切换

2.1什么是上下文切换

上下文切换其实就是工作环境的切换,其主要步骤如下:

  • 将前一个CPU的上下文保存起来
  • 加载新任务的上下文到寄存器和程序计数器(CPU寄存器是CPU内置容量小但是速度极快的内存,程序计数器是正在执行或即将执行的指令位置)
  • 跳转到程序计数器所在的代码,开始执行

在这里插入图片描述

2.2如何减少上下文切换

线程发生上下文切换时主要发生在如下两种情况中:

  1. 线程运行的时间片时间用完了,线程切换。
  2. 若线程在时间片结束前阻塞或结束,线程切换。

所以,基于以上两点,提出如下优化方案:

  1. 无锁并发编程,多线程竞争锁时,可能会因为获取不到锁而阻塞,产生如上条件2而进行上下文切换,通过无锁并发编程,比如对任数据ID进行hash,不同线程处理不同数据段,以此来减少因为线程阻塞而带来的上下文切换。
  2. CAS算法,通过CAS算法,可以在不加锁的情况下,循环等待来更新数据,以此来减少上下文的切换。
  3. 使用最少线程,避免创建不必要的线程,不然,很多处于等待状态。
  4. 使用协程,在单线程里实现多任务调度,并在单线程里维护多个任务间的切换。

三.死锁对并发编程的影响

多线程能够极大地提高程序运行的效率,但是如果不正确的使用多线程,难免会带来灾难性的错误,其中最常见的就是死锁。

所谓死锁就是线程1拥有A锁,等待B锁,线程2拥有B锁等待A锁,那么出现这种彼此等待的情况会导致线程举步不前,还会耗费大量的资源。

如何避免成为一个写BUG程序员,对于死锁,可注意一下几点:

  • 避免一个线程获得多个锁
  • 避免一个线程在锁内占有多个资源
  • 定时锁的使用
  • 对于数据库 加锁何解锁必须在一个数据库连接里

四.资源限制对并发编程的影响

如果服务器的带宽只有2M/s,某个资源的下载速度时1M/s,那么开启10个线程不会让下载速度达到10M/s,相反,它可能会因为上下文切换而小于2M/s,所以,使用多线程时,还需要考虑资源的限制。

资源限制主要考虑硬件资源和软件资源的影响,对于硬件资源,可以考虑用集群并行执行程序,对于软件资源,可以考虑使用资源池将资源复用。

看完这篇文章,你学废了以下内容么:

1.什么是并发编程?并发编程一定快么?

2.什么是上下文切换?如何减少上下文切换?

3.死锁对并发编程的影响,如何避免死锁的出现?

4.资源限制对并发编程的影响,如何改善资源的瓶颈?

看完这篇文章,你学废了以下内容么:

1.什么是并发编程?并发编程一定快么?

2.什么是上下文切换?如何减少上下文切换?

3.死锁对并发编程的影响,如何避免死锁的出现?

4.资源限制对并发编程的影响,如何改善资源的瓶颈?

注:本文总结于Java并发编程的艺术和个人所学

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值