当前位置: 首页>后端>正文

Java进阶-并发-基础

一、线程基础

参考链接:Java多线程-合集

1.1 基本概念

??进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位,即CPU分配时间的单位 。

  • 原子性:和数据库事务中的原子性一样,满足原子性特性的操作是不可中断的,要么全部执行成功要么全部执行失败
  • 可见性:一个线程对变量的值进行了修改,其他线程能够立即得知这个修改
  • 有序性:程序执行的顺序按照代码的先后顺序执行
Java进阶-并发-基础,第1张
Java线程状态迁移图.png
Java进阶-并发-基础,第2张
Java进阶-并发-基础,第3张
Java内存模型.png
Java进阶-并发-基础,第4张
运行时数据区.png

1.2 AQS-抽象队列同步器

Java进阶-并发-基础,第5张
AQS模型.png

AbstractQueuedSynchronizer
https://www.jianshu.com/p/8eadabbcc5a9

1.3 线程池

Java进阶-并发-基础,第6张
线程池状态转化图.png
Java进阶-并发-基础,第7张
任务执行过程.png

线程池

1.4 同步/异步/阻塞/非阻塞

  • 同步与异步描述的是进程/线程相互通信的方式,同步是由调用者主动等待调用的结果,异步是被调用者通过状态、通知等通知调用者, 或通过回调函数处理调用。
  • 阻塞和非阻塞描述的是进程/线程在进行I/O操作时的状态,阻塞是指调用结果返回之前,当前线程会被挂起,非阻塞是指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

https://www.zhihu.com/question/19732473
https://blog.csdn.net/qq_39515350/article/details/120854214

二、JUC包

  • volatile:单例模式-DCL(双端检测)机制。
instance =  new Test();
//读取到的instance不为null,instance引用对象可能没有完成初始化
memory = allocate();  // 1 分配对象内存空间
instance(memory);  // 2 初始化对象
instance = memory;  // 3 设置instance指向分配的内存地址,此时!=null
步骤2和3不存在数据依赖关系,可能存在指令重排
  • CAS:底层原理-自旋锁 & Unsafe类(底层汇编),时间戳原子引用解决ABA问题。
//AtomicInteger#getAndIncrement
public final int getAndIncrement() {
    //this-当前对象 valueOffset-内存地址偏移量
    return unsafe.getAndAddInt(this, valueOffset, 1);  
}

//Unsafe类
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        //主内存真实的值 不断自旋-获取主内存的值
        var5 = this.getIntVolatile(var1, var2);
        //var5 + var4更新值返回 true -- 自旋 比较值
     } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    return var5;
}
  • List:CopyOnWriteArrayList
//写时复制思想,读写分离
public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}
  • Set:CopyOnWriteArraySet
//底层也是CopyOnWriteArrayList
public CopyOnWriteArraySet() {
    al = new CopyOnWriteArrayList<E>();
}
  • Map:ConcurrentHashMap
  • CountDownLatch:使一个线程等待其他线程各自执行完毕后再执行
  • CyclicBarrier:让所有线程都等待完成后才会继续下一步行动
  • Semaphore:1)用于多个共享资源的互斥使用 2)用于并发线程数的控制

CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。Semaphore和锁类似,它一般用于控制对某组资源的访问权限

  • 死锁:两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉它们都将无法推进下去。
jps -l 
jstack -l pid > jstack.out  
https://fastthread.io/
  • ThreadPool:控制运行的线程数量,底层是阻塞队列
CPU密集型:任务需要大量的计算,没有阻塞,CPU一致全速运行;公式:CPU核数+1个线程的线程池。
I/O密集型:公式:2*CPU核数;公式:CPU核数/(1-阻塞系数),阻塞系数在0.8~0.9之间。
//获取PCU核数
Runtime.getRuntime().availableProcessors()
  • ThreadLocal:把ThreadLocal看成一个全局Map<Thread, Object>,每个线程获取ThreadLocal变量时,总是使用Thread自身作为key。相当于给每个线程都开辟了一个独立的存储空间,各个线程的ThreadLocal关联的实例互不干扰。

  • 锁:对象锁是用来控制实例方法之间的同步,而类锁是用来控制静态方法(或者静态变量互斥体)之间的同步的

https://www.shangmayuan.com/a/5845a0a8e2dc4e86b7f3c143.html


https://www.xamrdz.com/backend/3zg1922534.html

相关文章: