1. 上下文切换

1.1 上下文切换怎么来的

即使是单核cpu也支持多线程,cpu是通过给每个线程分配cpu时间片来实现这个机制的,一般时间片只有几十毫秒,所以当一个时间片执行完后,cpu会保存当前时间片内执行的任务状态,然后在切换到下一个时间片在执行其他任务,保存任务状态是为了下次再次切换到对应任务时可以加载出任务的状态

1.2 上下文切换带来的问题

上下文切换是会带来系统开销的,当任务量不大的情况下,开过多的线程处理不仅不会加快程序的处理速度,反而会拖慢,正是因为系统运行多出了线程创建和上下文切换的开销

1.3 如何解决或减少上下文切换

  • 无锁并发编程

    多线程下在使用锁的场景中,经常会因为竞争锁的使用权,导致频繁的上下文切换,如果此时避免使用锁,则可以减少上下文切换

  • CAS算法

    java的Atomic包的实现就是使用了CAS算法来更新数据,目的就是不使用锁,提高了程序效率

  • 减少线程的使用

    根据任务量合理的分配创建线程,避免线程空转,从而降低上下文切换的次数

  • 使用协程

    单线程内使用多任务调度的方式,避免多线程的使用,从而避免上下文切换

2. 死锁

2.1 死锁的原因

  • 一个线程内同时获取多个锁,导致在多线程下,多个线程互相持有其他线程要申请的锁,进而导致死锁
  • 持有锁的线程由于异常情况导致锁未释放,导致其他线程无法获取锁,导致死锁

    2.2 死锁带来的后果

    程序死锁后,会导致服务直接不可用,不能再对外提供服务,而且出现死锁的情况,很难定位问题,只能通过dump线程查看问题缘由

2.3 如何避免死锁

  • 避免一个线程同时获取多个锁
  • 避免一个线程在同一个锁内占用操作多个资源
  • 使用定时锁,lock.tryLock(timeout)可以在时间超时后自动返回,不会一直阻塞获取锁,避免了程序hang死
  • 操作数据库锁是,加锁和解锁必须在一个数据库连接中进行,否则会导致解锁失败,导致死锁

    3. 硬件或软件资源受限

    3.1 资源受限是什么

    资源受限是指在进行并发编程时,程序的执行速度受制于计算机硬件或软件资源 比如计算机带宽只有1M,你即使开再多线程,也只能达到1M的下载速度

3.2 资源受限带来的问题

在资源受限的机器上,多线程任务处理很有可能编程全部串行之行的情况,这样的情况下,由于引入了线程创建和上下文切花的开销,实际处理速度甚至比单线程的处理速度还要慢

3.3 如何解决资源受限带来的问题

  • 对于硬件,我们可以增加机器设备,讲任务分散到不同的机器上同步执行,这样就可以提高任务的执行速度了
  • 对于软件,可以采用线程池来代替频繁创建线程,能复用的资源尽量复用,这样在减少资源消耗的情况下,就可以提高程序运行的整体效率