并发编程理论基础一——概念简述

1、线程,进程,协程

  • 进程

一个运行起来的程序或软件;

操作系统分配资源的最小单位;

同一时刻运行的进程数不超过CPU核心数;

进程拥有自己的地址空间,启动进程时需要向操作系统申请系统资源

  • 线程

cpu调度和执行的基本单位;每个线程拥有独立的运行栈和程序计数器

线程和进程的联系:

进程拥有自己的资源空间,一个进程包含若干个线程,线程与CPU资源分配无关,多个线程共享同一进程内的资源(内存地址空间和内存单元)

进程的调度和切换比线程慢,资源开销大

进程之间不共享全局变量,同一进程下的多个线程之间共享全局变量

  • 协程

coroutine,java中貌似没这个概念,go中有,不懂,仅做下对比

一种用户态的轻量级线程;

协程切换时无需线程上下文切换的开销;

无需原子操作锁定及同步的开销;

方便切换控制流,简化编程模型;

 2、并发和并行

一个任务可能是进程,也可能是线程,这里统称为任务

  • 并行:针对多核CPU而言,多个核心同时执行多个不同任务的能力
  • 并发:针对单核CPU而言,指的是CPU通过时间分片技术交替执行不同任务的能力

多核CPU中,并发和并行一般都会同时存在

3、阻塞和非阻塞

  关注的是程序在等待调用结果(消息,返回值)时的状态.

  • 阻塞:指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回
  • 非阻塞:指在不能立刻得到调用结果之前,该调用不会阻塞当前线程

4、同步和异步

  • 同步:调用结果返回之前,进程一直等待,直到拿到返回结果才继续后续操作
  • 异步:不导致请求进程阻塞的设计就是异步的

5、为什么要使用多线程

简单说就是为了充分发挥CPU的优势,充分利用CPU资源,为了性能

6、线程安全

  引用《并发编程实践》中的一个定义描述:当多个线程访问某个类时,这个类始终都能表现出正确的行为,

就称这个类是是线程安全的

7、上下文切换

  CPU通过时间分片来执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会

保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。

  任务从保存到加载的过程就是一次上下文切换上下文切换会影响多线程的执行速度

8、多线程关注哪些问题

(1)安全性问题

(2)活跃性问题

  • 死锁和活锁:死锁时两个线程都处于阻塞状态,都想获得对方手上的某个锁,但是都不释放;

活锁不会阻塞线程,但是两个线程一直tryLock,但是都过于主动让出资源,反而没有人真正使用临界区资源

维基百科中的一个形象例子:两个人在路口相遇碰上了,都没有等对方让路,而是都很有礼貌的给对方让路,

但是两个人都在不断朝路的同一个方向移动,这样只是在做无用功,还是不能让对方通过
  • 饥饿:线程由于某种原因迟迟无法访问它所需要的资源

(3)性能问题

9、发布和逸出

  • 发布:发布一个对象,就是使对象能够在当前作用域之外的代码中使用
  • 逸出:当某个不该发布的对象被发布时就被称为逸出

10、不可变对象

  某个对象在被创建后,其状态就不能被修改,这个对象称为不可变对象,不可变对象一定是线程安全的,如String

还有一个事实不可变对象,指的是对象从技术上来看是可变的,但是其状态在发布后不会再改变,这个对象就称为事实不可变对象

11、线程死锁

       两个或多个线程互相持有对方所需要的资源,导致这些线程处于相互等待状态,若无外力作用,他们将无法继续执行下去

       原因概括:当前线程拥有其他线程需要的共享资源;当前线程等待其他线程释放自己需要的资源;都不放弃

       四个必要条件:互斥,占有且等待,不可抢占,循环等待

       如何预防:尽量减少嵌套同步,尽量减少锁的定义,一次性申请好锁,申请不到锁时主动释放,如JUC Lock里的tryLock(synchronized就是不释放的典型),获取锁时避免顺序交叉

 

posted @ 2021-03-07 23:04  鼠标的博客  阅读(66)  评论(0编辑  收藏  举报