Java并发(一)_并发编程的优缺点

并发编程的优缺点

思维导图:

Java并发(一)_并发编程的优缺点

1. 为什么要用并发

  • 并发编程可以将多核CPU的计算能力发挥到极致,提高性能
  • 面对复杂业务模型,并发程序会比串行程序更适应业务需求,并发程序更能吻合这种业务拆分

2.并发编程有哪些缺点

2.1 频繁的上下文切换

  • 概念

    • 时间片是CPU分配给各个线程的时间,因为时间非常短,所以CPU不断通过切换线程,让我们觉得多个线程是同时执行的,时间片一般是几十毫秒。而每次切换时,需要保存当前的状态起来,以便能够进行恢复先前状态,而这个切换时非常损耗性能,过于频繁反而无法发挥出多线程编程的优势。
  • 解决办法

    • 无锁并发编程:可以参照ConcurrentHashMap锁分段的思想,不同线程处理不同段的数据,这样在多线程竞争的条件下,可以减少上下文切换的时间
    • CAS算法:利用Atomic下使用CAS算法来更新数据,使用了乐观锁,可以有效的减少一部分不必要的锁竞争带来的上下文切换
    • 使用最少线程:避免创建不必要的线程,比如任务很少,但创建了很多线程,这会造成大部分线程都处于等待状态
    • 协程:在单线程中实现多任务的调度,并在单线程中维持多个任务间的切换

2.2 线程安全

  • 死锁

    • 举例:两个线程Thread1(拥有LOCK1,需要LOCK2)和Thread2(拥有LOCK2,需要LOCK1)它们分别占有各自需要的锁,但又得不到各自需要的锁,就会无止的等待下去,造成了死锁

    • 解决办法

      • 避免一个线程持有多个锁
      • 避免一个线程在锁内部占用多个资源,尽量保证一个锁占用一个资源
      • 尝试使用定时锁,使用lock.tryLock(timeOut),当超时等待时当前线程不会阻塞
      • 对于数据库锁,加锁和解锁必须在同一个连接里,否则会出现解锁失败的情况

3.需要了解的概念

3.1 同步vs异步

  • 同步:调用者必须等待调用的方法结束后,调用者后面的代码才能执行。
  • 异步:调用者不用管调用的方法是否完成,都会执行后面的代码,当被调用的代码完成后会通知调用者

3.2 并发与并行

  • 并发是指多个任务交替执行
  • 并行是指真正意义上的同时进行,单个CPU是无法做到并行的,真正的并行只能出现在拥有多个CPU的系统中

3.3 阻塞和非阻塞

  • 用来形容线程间的相互影响
  • 阻塞:比如一个线程占有了临界区资源,而其他线程需要这个资源就必须等待该资源的释放,会导致等待的线程挂起,这就是阻塞
  • 非阻塞:而非阻塞就恰好相反,它强调没有一个线程可以阻塞其他线程,所有线程都会尝试着向前执行

3.4 临界区

  • 用来表示一种公共资源或者说是共享数据,可以被多个线程使用。但每个线程使用时,一旦临界区的一个资源被一个线程占有,其他线程必须等待

小结:

简单阐述了并发的概念和为什么要使用并发,并发的缺点和解决办法,以及一些相关的概念。

参考资料

1.  github: Java-concurrency-master

2.《Java并发编程的艺术》