🐴🐴🐴进程和线程的区别
由来
进程是资源分配最小单位 线程是CPU调度最小单位
区别
JAVA进程和线程的关系
JAVA程序默认一个main主线程 但JVM会创建多个线程 GC线程
🐴🐴🐴run和start方法的区别
🐴🐴🐴thread和runnable的关系
🐴🐴java向多线程中传递参数的三种方法详细介绍
https://www.jb51.net/article/31981.htm
构造函数
成员变量
回调函数
🐴🐴🐴🐴如何实现处理线程的返回值
🐴主线程等待法 不精准
🐴调用线程join()方法阻塞等待 线程处理结束 (粒度不够细)
https://blog.csdn.net/q5706503/article/details/84592449
🐴FutureTask/线程池(Future) 获取返回值
线程池可以提交多个callable任务 对任务进行管理
🐴🐴线程的状态 Thread类里的enum状态 结束之后再调用会抛 非法状态异常
🐴🐴🐴sleep和wait方法的区别
实例
🐴🐴🐴notify和notifyAll方法的区别
🐴🐴锁池 等待池
锁池为 线程A 给变量上锁阻塞后 阻塞的其他线程进入锁池 ENTRY LIST
等待池为 线程A wait之后进入等待池 被notify之后 重新进入锁池 竞争对象锁 WAIT SET
🐴🐴🐴yield
暗示线程调度器 让出当前cpu资源 (对锁无影响)
🐴🐴🐴interupt
如果被interupt了 检查flag
线程状态的改变
线程间的状态转换:
-
新建(new):新创建了一个线程对象。
-
可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
-
运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
-
阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
- 死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
🐴🐴🐴线程安全的原因
🐴🐴🐴synchronized互斥对象锁特点
🐴🐴对象锁(方法锁)和类锁
对象锁 锁对象
类锁 锁类 类的所有对象 类锁对象锁 互不干扰
🐴🐴总结
🐴🐴🐴🐴synchronized底层原理
JAVA对象头
monitor
🐴🐴对象头
基本结构 存储堆中
🐴🐴monitor锁 对象与生俱来 在java对象头中
与 重量级锁 域相关联
monitor锁源码 ObjectMonitor
🐴🐴字节码 对象锁 与 方法锁 实例
隐式 ACC_SYNCHRONIZEDflag
多出的moniterExist为处理异常 释放monitor的指令
🐴🐴锁的重入
当对象拥有该对象锁时 内部再嵌套 该对象锁 依然可以
🐴🐴synchronized缺点 (前期)
前期 重量级锁 效率低
🐴🐴🐴🐴synchronized优化
🐴🐴自旋锁
🐴🐴自适应自旋锁 JVM根据之前自旋时间 决定自旋时间
🐴🐴锁消除
🐴🐴锁粗化 一连串操作 对一个对象加锁 jvm会将加锁范围粗化到 一系列操作的外部 上一次锁
🐴🐴synchronized四种状态 锁膨胀 和锁降级
🐴🐴偏向锁 当线程获得锁时 记录线程id 之后不需要CAS操作加锁
缺点:不适合 锁竞争激烈的 情况
🐴🐴轻量级锁 自旋
jvm实例
解锁过程
锁的内存语意 释放锁就是写到主内存中 获取锁是读主内存的修改
markword在主存 堆中 display mark word为 本地复制
🐴🐴特点总结
🐴🐴吞吐量 暂停时间
吞吐量为宏观 整体侧重
暂停时间为 单次暂停侧重
🐴🐴JSTACK分析线程 堆
https://www.cnblogs.com/kongzhongqijing/articles/3630264.html
🐴🐴🐴🐴synchronized和reentrant锁(再入锁)的区别
继承AQS abstract queue synchronizer
🐴🐴公平锁 避免饥饿情况(等待太久) 实现公平有额外开销
🐴🐴reentrant lock有点 syn做不到的地方
🐴🐴wait notify notifyAll对象化
ArrayBlockingQueue 内部实现 互斥锁 Condition
https://blog.csdn.net/qq_33788242/article/details/89765928
signal /await
🐴🐴condition
https://www.jianshu.com/p/1c52f17efaab
syn和reentrant区别
但是ReentrantLock提供了tryLock()、tryLock(long timeout, TimeUnit unit)、lock.lockInterruptibly()
tryLock() 方法试图申请一个锁,在成功获得锁后返回true,否则,立即返回false,而且线程可以立即离开去做其他的事情。
tryLock(long timeout, TimeUnit unit) 是一个具有超时参数的尝试申请锁的方法,阻塞时间不会超过给定的值;如果成功则返回true
lockInterruptibly() 获得锁,但是会不确定地发生阻塞。如果线程被中断,抛出一个InterruptedException异常。
🐴🐴JMM java内存模型
🐴🐴
🐴🐴工作内存
🐴🐴JMM与堆栈区别
🐴🐴主内存 /工作内存 区别 类似于 本地栈 与 堆的区别
🐴🐴🐴🐴JVM解决可见性问题
🐴🐴🐴happens before 原则 是判断是否线程安全的原则
🐴🐴🐴happens before 概念
如果happens before则 B可见A的修改
如果不 JVM可以重新排序
🐴🐴🐴volatile轻量级锁 并非绝对安全 保证写操作都被别的线程看到
🐴🐴🐴volatile实现原理
🐴🐴如何保证可见性
写时 会吧工作内存 刷新到主内存
读时 无效后只能从主内存中读取共享变量
🐴🐴如何禁止重排优化 内存屏障 保证了不重排 和 可见性
解决:给instance加上volatile 禁止重排
🐴🐴🐴🐴volatile和syn的区别
🐴🐴CAS 乐观锁
思想
一般不需要开发者去实现CAS
缺点
🐴🐴线程池 因为线程新增销毁 开销大 来重复利用
使用的原因
🐴🐴FORK JOIN
🐴🐴Executor的框架 都指向 excutor excutorService Scheduled
executor service为callable scheduled添加 定期
🐴🐴🐴🐴线程池处理任务逻辑(自定义线程池)
🐴🐴线程池构造函数
🐴🐴饱和处理策略
🐴🐴execute执行逻辑
🐴🐴ctl保存线程池状态 高3位为状态 后面为worker数
🐴🐴线程池的状态
🐴🐴线程池大小设定