进程和线程

  • 进程是程序运行资源分配的最小单位

    • 资源:CPU、内存、磁盘IO等
    • 进程间相互独立,同一个进程间多个线程共享该进程的全部资源
    • 运行一个程序就是启动了一个进程,程序是死的,进程是活的
  • 线程是CPU调度的最小单位,必须依赖于进程而存在

    • 线程本身只有很少的系统资源(程序计数器、栈)
    • 可以和属于同一个进程的其他线程共享进程的系统资源

CPU核心数和线程数的关系

  • 多核心:单芯片多处理器,将多个处理器集成到一个芯片上,各个处理器执行不同的进程

    • 并行处理:多个CPU同时并行的运行程序
  • 多线程:同一个处理器上的多个线程同步执行,并共享处理器的执行资源

    • 并发处理:侧重于多个任务交替执行,处理器同一时刻只会有一个线程在执行
  • 核心数、线程数:通常CPU都是多核的,增加核心数的目的就是为了增加线程数

    • 操作系统就是通过线程来执行任务的,所以线程线程数越多,处理能力越强
    • 正常情况下,核心数:线程数 = 1:1;利用intel的超线程技术可以达到1:2的关系

CPU时间片轮转机制

也称为RR调度

  1. 每个进程被分配一个时间段(时间片,表示进程允许运行的时间)
  2. 如果在时间片结束时进程还在运行,该进程的CPU将被剥夺并分配给另一个进程
  3. 如果进程在时间片结束前阻塞或者完成,立即切换CPU资源给下一个进程
  4. 调度程序需要做的就是维护一张就绪进程表(FIFO队列),当有进程用完它的时间片后,将它移动到队列末尾

指令寄存器:存放当前正在执行的指令 程序计数器:存放下一条要执行的指令地址

时间片长度
进程之间切换时需要保存和装入寄存器值以及内存映像,更新各种表格和队列,这是需要一定时间的。所以时间片的长度设置非常重要,不能过大或者过小

  • 过大,近似变成串行了,可能引起对要求响应时间比较短的交互请求响应变差
  • 过小,进程间频繁切换消耗大量时间,降低了CPU的效率

并行和并发

  • 并发侧重于多个任务交替执行
  • 并行表示同时执行多个任务

临界区

一种可以被多个线程共享的数据,但是同一时刻只能有一个线程使用

阻塞和非阻塞

  • 阻塞:一个线程占用临界区资源时,其他需要这个资源的线程必须在临界区等待,导致线程挂起
  • 非阻塞:一个线程不能阻止其他线程的执行,所有线程都会尝试不断向前执行

活跃性问题

  • 死锁

    • 死锁的必要条件
    • 如何避免死锁
  • 饥饿

    • 线程由于无法访问它需要的资源而不能执行时,就发生了饥饿
    • 最常见引发饥饿的资源就是CPU时钟周期。如果线程的优先级使用不当,或者持有锁时执行一些无法结束的逻辑(无限循环等),也可能发生饥饿
    • 多数java应用中,所有线程优先级相同,尽量不要改变线程的优先级,否则可能会发生饥饿问题
  • 活锁

    • 两个线程请求资源时,互相“谦让”,主动将资源让给对方,导致没有一个线程能够同时拿到所有资源
    • 通常发生在处理事务消息的程序中
      • 如果消息处理器不能处理某种特定类型的消息,发生错误回滚事务,并且将其重新放在队列开头,这样虽然处理消息的线程没有阻塞,但是也不能继续执行
        • 这个问题的原因是过度的错误恢复代码造成的,将不可修复的问题错误的当作可以修复的问题
    • 解决活锁的办法是在重试机制中引入随机性

高并发的好处

  1. 充分利用CPU资源(多核多线程CPU)
  2. 减少响应用户的时间
  3. 代码模块化、异步化、简单化(电商系统拆分订单系统、短信系统、邮件系统等)

使用多线程注意事项

  • 线程之间的安全性,注主要针对的是共享资源
  • 线程间的死锁
  • 线程数量过多导致服务器资源耗尽宕机

JMM

原子性

一个操作是不可中断的,一旦开始,要么成功要么失败,不会被其他线程干扰

  • 基本类型的读写是原子性的,long和double除外【把它们当成2个原子性的32位值】

    • 可以使用volatile实现long和double读写的原子性,这是volatile在原子性上的唯一贡献
  • JVM规范规定

    • 实现对普通long与double的读写不要求是原子的(但如果实现为原子操作也OK)
    • 实现对volatile long与volatile double的读写必须是原子的(没有选择余地)

可见性

一个线程修改了某个共享变量的值后,其他线程是否能够立即知道这个修改

有序性

单线程或者多线程串行环境下指令重排是没有任何问题的,但是多线程并行时可能会出现问题

指令重排可以提高CPU的处理性能,是必要的

happen-before原则(重排序不会破坏的原则)