并发知识点整理

  • 并发
    • 一 原子性、可见性、有序性
    • 二 进程三态
    • 三 JVM线程中的状态
    • 四 CAS操作解析(一种锁粒度极低的乐观锁)
    • 五 synchronized带来的重度锁,和线程一开始的偏向锁,和轻量级锁
      • 5.1 Java对象
      • 5.2 锁如何升级
    • 六 ThreadPoolExecutor线程池的概念和参数解析
      • 6.1 主要参数
      • 6.2 拒绝策略
      • 6.3 线程池的两种提交方式 submit 和 execute
      • 6.4 workQueue
    • 七 java中的并发集合

并发

一 原子性、可见性、有序性

1)原子性: 内存模型的原子性变量操作
2)可见性:因为在执行过程中,每个一个线程都有自己单独的内存空间,只有通过(volatile,synchronized,final)新值才能够立即进入到主存之中
3)有序性:线程内有序,线程间无序。通过,先行发生原则和,volatile,synchronized

二 进程三态

1)
运行态 —> 阻塞态:正在执行的进程因为某种等待事件无法执行,就进入了阻塞态
运行态 —> 就绪态:分配给每个进程的时间片是有限的,运行时间片使用完成之后或者出现更高优先权进程就进入到就绪态
就绪态 —> 运行态: 由CPU进行调度,选中一个进程分配时间片执行
阻塞态 —> 运行态: 进程所等待的事件已经发生

三 JVM线程中的状态

  1. 线程创建
  2. 线程在可运行状态
  3. 在线程未争取到锁对象的时候,线程进入锁阻塞,等待获取锁对象,进入可运行状态
  4. 线程获取到锁对象,但是调用了wait()方法,进入了无线等待中,等待其他线程调用notify(),只有获取锁对象才进入到可运行状态
  5. sleep时间到,或者wait时间到,进入到计时等待,时间到获取到锁对象才能进入可运行状态,时间到未获取到锁对象就进入锁阻塞状态
  6. 线程终止

四 CAS操作解析(一种锁粒度极低的乐观锁)

AtomicInteger.incrementAndGet();

public final int incrementAndGet() { 
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int getAndAddInt(Object var1, long var2, int var4) { 
    int var5;
    do { 
    var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    return var5;
}

1.它包含 3 个参数 CAS(V,E,N),V表示要更新变量的值,E表示预期值,N表示新值。仅当 V值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做两个更新,则当前线程则什么都不做。最后,CAS 返回当前V的真实值。

2.compareAndSwapInt 是一个native接口

3.底层实现原理: 通过 mov 指令 ,移动exchange_value 等值 ,进入寄存器中,然后通过累加器,进行值的计算,最后通过总线,刷新主存,达到效果

五 synchronized带来的重度锁,和线程一开始的偏向锁,和轻量级锁

5.1 Java对象

  1. 对象头+实例数据+对齐填
  2. Mark Word+指向对象所属的类的指针组成(如果是数组对象,还会包含长度

5.2 锁如何升级

  1. 偏向锁 —> 轻量级锁 —>重量级锁
  2. 偏向锁升级:当一个线程获得了偏向锁,在执行时,只要有另一个线程尝试获得偏向锁,并且当前持有偏向锁的线程还在同步块中执行,则该偏向锁就会升级成轻量级锁。
  3. 轻量级锁升级:用CAS操作将锁的Mark Word替换为自己线程栈中拷贝的锁记录的指针。如果成功,当前线程获得锁,如果失败,表示Mark Word已经被替换成了其他线程的锁记录,说明在与其它线程竞争锁,当前线程就尝试使用自旋来获取锁。当自选次数超过一定次数,就升级为重量级锁

六 ThreadPoolExecutor线程池的概念和参数解析

6.1 主要参数

参数名 参数含义
corePoolSize 核心线程数
maxinumPoolSize 最大线程数
keepAliveTime 空闲线程存活时间
unit 存活时间的单位
workQueue 存放线程任务队列
threadFactory 线程工厂,创建新线程
handler 线程池拒绝处理后的任务

corePoolSize : 代表核心线程数,这些线程创建以后并不会被消除,而是一种常驻线程
maxinumPoolSize : 表示最大允许被创建的线程数,当核心线程数都用完时
workQueue : 用来存放待执行的任务,假设我们现在核心线程都已被使用,还有任务进来则全部放入队列,直到整个队列被放满但任务还再持续进入则会开始创建新的线程
keepAliveTime、unit : 表示超出核心线程数之外的线程的空闲存活时间,也就是核心线程不会消除,但是超出核心线程数的部分线程如果空闲一定的时间则会被消除
threadFactory : 线程工厂,用来生产线程执行任务
handler : 有两种触发任务拒绝策略的方法,1.调用shutdown 2.线程池内已经达到最大线程数,这个时候也是拒绝

6.2 拒绝策略

  1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
  2. ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
  4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

6.3 线程池的两种提交方式 submit 和 execute

  • execute只能提交Runnable类型的任务,无返回值。submit既可以提交Runnable类型的任务,也可以提交Callable类型的任务,会有一个类型为Future的返回值,但当任务类型为Runnable时,返回值为null。
  • execute在执行任务时,如果遇到异常会直接抛出,而submit不会直接抛出,只有在使用Future的get方法获取返回值时,才会抛出异常。

6.4 workQueue

  1. SynchronousQueue:阻塞队列
  2. LinkedBlockingQueue:无限队列
  3. ArrayBlockingQueue:由数组支持的有界阻塞队列,FIFO

七 java中的并发集合

  1. CopyOnWriteArrayList相当于线程安全的ArrayList

  2. CopyOnWriteArraySet相当于线程安全的HashSet

  3. ConcurrentHashMap相当于线程安全的HashMap

  4. ConcurrentSkipListMap相当于线程安全的TreeMap

  5. ConcurrentSkipListSet相当于线程安全的TreeSet

  6. ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列

  7. LinkedBlockingQueue是单向链表实现的(可指定大小)阻塞队列

  8. ConcurrentLinkedQueue是单向链表实现的无界队列

本文地址:https://blog.csdn.net/m0_37111373/article/details/113944012