Tips:一个Native方法往往意味着这个方法没有使用或无法使用平台无关的手段来实现(依赖平台资源的方法)
自问自答
Q:为什么会有锁出现
A:多线程操作同一数据,防止数据不一致
Q:为什么锁有很多种类
A:一开始没有,就是直接的锁定数据对象,OS让其他线程挂起,后面在换新,对性能损耗很大。后来大牛闲了有空了,就开始对性能做了优化,开始了有不同种类的策略去应对多线程的场景。
实现线程的三种方法
- 使用内核线程实现(Kernel-level Thread,KLT)程序一般不会直接使用而是使用高级接口轻量级进程(Light Weight Process ,LWP)1:1
- 使用用户线程实现,缺点:自己得实现很多系统内核做的事情
- 两者混合
Java使用的是内核线程实现
不过也得看对应的操作系统支持什么线程模型,之前也使用过用户线程实现
线程的两种调度方式
- 协同式线程调度(排队一个一个,缺点前面不动后面都不动系统死了)
- 抢占式线程调度(Java使用,系统分配线程执行时间,用完就排别人)
线程的一生
| 名称 | - | 效果 |
|---|---|---|
| 新建 | New | 创建后尚未启动的线程处于这种状态 |
| 运行 | Runnable | 操作系统线程状态的Running和Ready,也就是处于此状态的线程可能正在执行,也可能正在等待CPU为他分配执行时间 |
| 无限等待 | waiting | 被wait,这种状态不会被分配CPU执行时间,得被其他线程唤醒notify |
| 有限等待 | Timed waiting | 限期时间内不会被分配CPU执行时间 |
| 阻塞 | Blocked | 等待其他线程的一个排他锁 |
| 结束 | Terminated | 已经终止线程的线程状态 |
锁优化
| 名称 | 效果 |
|---|---|
| 自旋锁 | 让其他等待线程不挂起,只是执行些空循环等一下锁线程,等待的时间固定 |
| 自适应自旋锁 | 会有一个时间计算策略,如果上一次等待成功过,就等久点。如果没有,可以直接去挂起等待唤醒 |
| 锁消除 | 不过明显对象不会被其他线程使用,JTL编译器会自动去除锁 |
| 锁扩大 | 如果是类似遍历里面加锁,为了防止频繁的加锁解锁,扩大到遍历语句外层 |
| 轻量级锁 | - |
| 偏向锁 | - |