相关概念
进程与线程的区别
本质区别:线程是CPU调度的基本单位,进程是操作系统资源分配的基本单位,在Linux中,二者都是使用task_struct结构体表示。
多线程
线程的实现方式
1 编写一个类,继承Thread类,重写run()方法,创建线程对象,并调用start开启线程。
(线程开启不一定立即执行,由cpu调度执行)
线程的状态
线程状态转化图
线程的相关方法
线程优先级
守护线程
线程同步
synchronized关键字
Monitor 工作原理
Mark Word 一共8个字节
锁记录里面的数据(锁记录地址和状态)和对象中的Mark Word 进行交换。
自旋锁优化
主要针对重量级锁的时候,可以使用自旋锁进行优化
偏向锁
撤销偏向锁 : 1 调用对象hashcode 2、当有其他线程使用对象 3 调用wait/notify
wait/notify 原理
为什么wait用while而不用if?
使用while而不是使用if 主要是为了解决虚假唤醒的问题,notify可以唤醒所有waitset里面的所有等待的线程。如果使用notify会随机唤醒一个正在等待的线程,也可能造成虚假唤醒的情况。所以正确的使用方式如上图。
可打断锁可以解决死锁的情况,被动的方式
锁超时 自动停止等待,可以解决哲学家就餐问题
volatile(易变关键字)
volatile 在jdk1.5才加上
volatile 可以解决dcl问题,
防止在对象引用未执行构造方法时先把对象引用赋值给INATANCE。
为什么synchronize 可以保证代码块的可见性?
synchronized关键字解决的是执行控制的问题,它会阻止其它线程获取当前对象的监控锁,这样就使得当前对象中被synchronized关键字保护的代码块无法被其它线程访问,也就无法并发执行。更重要的是,synchronized还会创建一个内存屏障,内存屏障指令保证了所有CPU操作结果都会直接刷到主存中,从而保证了操作的内存可见性,同时也使得先获得这个锁的线程的所有操作,都happens-before于随后获得这个锁的线程的操作。
具体执行过程可参考链接https://www.bilibili.com/video/BV1xK4y1C7aT?p=1
锁升级过程
ThreadLocal 解读