八股文4:高并发

本文深入探讨了Java并发编程的关键概念,包括进程与线程的区别、线程状态转换、线程池、锁机制如synchronized和volatile,以及并发容器如ConcurrentHashMap。还详细讲解了死锁预防、线程安全的单例模式实现以及并发工具如CountDownLatch和Semaphore的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

进程与线程的区别

在这里插入图片描述

线程状态及转换

在这里插入图片描述

什么是线程挂起(非可执行的状态)

在这里插入图片描述

线程的创建方法

在这里插入图片描述

一般使用匿名内部类实现或者使用labmda表达式

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

什么是守护线程

区别于非守护线程,一旦没有非守护线程,守护线程就会自动结束自己的生命周期,此时就会关闭jvm进程

在这里插入图片描述

什么是死锁和如何防止死锁

在这里插入图片描述

在这里插入图片描述

并发编程的三个重要特性

在这里插入图片描述

CAS原理(无锁)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

原子操作类

在这里插入图片描述

CAS实现原子操作的三大问题

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

synchronized关键字(不透明锁,方法/代码块)

synchronized 关键字最主要的三种使用方式:

在这里插入图片描述

synchronized 关键字底层原理属于 JVM 层面

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

volatile关键字(读写屏障,变量)

JMM(java内存模型)

在这里插入图片描述
在这里插入图片描述

volatile解决数据不一致问题

在这里插入图片描述
在这里插入图片描述

volatile的读写屏障

在这里插入图片描述

synchronized 关键字和 volatile 关键字的区别

在这里插入图片描述

Lock锁(类)—AQS原理AbstractQueuedSynchronizer

在这里插入图片描述
在这里插入图片描述

AQS资源共享方式(进行分类不同的阻塞同步锁)

在这里插入图片描述

ReentrantLock(独占方式)–(公平锁与非公平锁的区别)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ReentrantReadWriteLock(两种资源共享方式)

只有读读能共享,读写互斥,写写互斥:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

CountDownLatch倒计时器(多线程相互等待全部完成)–(应用场景)

在这里插入图片描述
在这里插入图片描述

CompletableFuture的异步并行与等待

在这里插入图片描述

Semaphore(限流器–限制共享资源线程的数量)

Semaphore(信号量)可以指定多个线程同时访问某个资源。实际相当于刚开始permits数量的上限线程同时访问某个资源,后面最多只有permits个线程可以使用这个许可证,其余的线程必须等待由许可的线程release才有机会获得许可!!(所以semaphore可以用作限流器)
在这里插入图片描述

可以发现countdownLatch只能减少至0,没有释放的操作。但是semphore有acquire占用state,也可以release释放资源,显示了state的复用的功能

在这里插入图片描述

限流器的应用

Synchronized和Lock之间的区别

在这里插入图片描述

并发容器(JUC包下)

ConcurrentHashMap(对比HashMap,HashTable)

添加链接描述

CopyOnWriteArrayList(读读共享)

在这里插入图片描述

ConcurrentLinkedQueue(CAS非阻塞队列)

在这里插入图片描述

ConcurrentSkipListMap(跳表)

不知道是维护了多级的指针还是维护了多个链表
在这里插入图片描述
在这里插入图片描述

Threadlocal(本地线程局部变量)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

TreadLocal的set方法:先拿到自己线程的ThreadLocalMap,然后将这个Threadlocal作为键,set进入的参数value作为值(get方法是类似的思想)

在这里插入图片描述
在这里插入图片描述

经典的例子
在这里插入图片描述
在这里插入图片描述

ThreadLocal的内存泄漏问题

在这里插入图片描述

在这里插入图片描述

线程池(框架Executor)

在这里插入图片描述
在这里插入图片描述

线程池的状态

在这里插入图片描述

创建线程池的方式 (Excutors静态方法 | ThreadPollExcutor的构造函数)

在这里插入图片描述

线程池中执行 execute()方法和 submit()方法的区别是什么呢?

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

ThreadPoolExecutor 类及其构造方法分析

构造方法参数分析
在这里插入图片描述
在这里插入图片描述

具体的线程分配情况–执行的原理

任务队列都满时,才会启用急救线程
在这里插入图片描述
在这里插入图片描述

线程用完时的拒绝策略

在这里插入图片描述
在这里插入图片描述

一个线程池执行任务的demo

step1:首先实现一个自己的Runnable(Callbable)接口,来实现自己执行任务的方法
step2: 使用ThreadPoolExecutor创建自定义的线程池,实际上就是调用它的"构造方法",创建"自己的参数的线程池"
step3: 使用“线程池的execute(myrunnable)”来提交执行任务(实现的myCallable使用submit提交任务,同时有future对象返回用于获取执行的结果)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

一些补充

指令重排序相关

在这里插入图片描述

在这里插入图片描述

as-if-serial语义(编译器优化重排序)

在这里插入图片描述

happens-before的定义(内存系统重排序)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Synchronized锁升级

在这里插入图片描述

在这里插入图片描述

偏向锁(减少CAS)

判断偏向锁的标志位是否为1,如果不为1,此时先尝试CAS轻量级锁
在这里插入图片描述

轻量级锁(Object:CAS自旋竞争)

为每个线程创建一个锁记录对象(存放在本线程的栈帧中,锁重入就会再创建一个锁记录对象放在栈帧中),将锁记录对象的object reference指向锁定对象 && 将锁地址与锁定对象的Markword的hashcode进行CAS尝试交换。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

锁膨胀(CAS自旋失败,Object申请Monitor)

在这里插入图片描述
在这里插入图片描述

重量级锁(Monitor–Owner&EntryList Blocked)

注意这张图:老式的直接重量级锁的情况,具体还是按照锁膨胀的那个为准,主要学习一下monitor的结构monitor的结构:(owner指向当前占用object对象的线程,entryList表示阻塞队列—后续锁释放会抢锁,waitSet等待队列–主动释放锁且需要唤醒才能加入阻塞队列进行抢锁)
在这里插入图片描述

owner重量级锁的线程wait()的原理

注意:wait和notify的方法属于object对象的!!(针对这个锁定对象object可以调用wait和notify分别用来对应waitset中的某个线程)

Object 类是一个特殊的类,是所有类的父类

public final native Class<?> getClass()//native方法,用于返回当前运行时对象的Class对象,使用了final关键字修饰,故不允许子类重写。

public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的HashMap。
public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户比较字符串的值是否相等。

protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常。

public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方法。


//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
public final native void notify()

//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
public final native void notifyAll()


//native方法,并且不能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。
public final native void wait(long timeout) throws InterruptedException

//多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。
public final void wait(long timeout, int nanos) throws InterruptedException


//跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
public final void wait() throws InterruptedException

protected void finalize() throws Throwable {
    }//实例被垃圾回收器回收的时候触发的操作

在这里插入图片描述

举个例子:

public class WaitNotify {
   
    public static void main(String[] args) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值