Java多线程
线程基础
进程:操作系统分配资源的最小单位
线程:CPU执行的最小单位
1. 用户线程
用户自己创建的业务线程;
2. 守护线程
为用户线程提供服务的线程,如GC;
通过thread.setDaemon(true);设为守护线程,且必须放在start方法前;
1. 继承Thread类;
2. 实现Runnable接口;
3. 实现Callable接口(可结合FutureTask返回结果,并支持抛出异常);
4. 通过线程池创建;
1. IO密集型
n = 2 * CPU核数
2. CPU密集型
n = CPU核数 + 1

1. sleep
让出cpu,不释放锁
2. wait
让出cpu,释放锁。依赖synchronized
thread.interrupt
通过抛出异常中断线程。
stop方法不推荐,会导致死锁
定义
代码经过编译器优化后才会执行,有种优化方式为:指令重排,而指令重排必须遵守Happens-Before原则
规则名称 | 描述 |
程序顺序规则 |
一个线程的每个操作,happens-before于该线程中的任意后续操作。 注:此处操作指前一个操作的结果对后一个操作可见,若不满足不允许重排。 |
监视器锁规则 |
对一个锁的解锁,happens-before于后续对这个锁的加锁。 |
volatile规则 |
对volatile变量的写,happens-before于后续对这个变量的读。 |
传递性 |
若 A happens-before B,B happens-before C,则 A happens-before C。 |
线程启动规则 |
Thread对象的start方法,happens-before这个线程后续任意操作。 |
线程终止规则 |
线程中任意操作,happens-before该线程的终止。 |
线程中断规则 |
对线程的interrupt操作,happens-before对该线程中断事件的检测。 |
对象终结规则 |
对象初始化完成,happens-before该对象的finalize方法。 |
锁
锁 | 定义 |
公平锁与非公平锁 |
公平锁:多线程按照申请锁的顺序获取锁。 eg:ReentrantLock可通过构造函数指定是否公平(默认非公平锁) 非公平锁:不按申请顺序获取锁,有可能造成饥饿锁。 eg:synchronized |
独享锁与共享锁 |
独享锁:一个锁只能被一个线程持有。 eg:synchronized与ReentrantLock都是独享锁。 共享锁:一个锁可被多个线程持有。 ReadWriteLock中,读锁是共享锁,写锁是独享锁。 |
乐观锁与悲观锁 |
乐观锁:对同一数据并发操作,认为不一定会更新数据,因此采取不断尝试更新的操作(如CAS自旋) 悲观锁:对同一数据并发操作,认为一定会更新数据,因此会加锁实现同步。 注:这两者不是具体的锁,是指看待并发同步的角度。 |
分段锁 |
细化锁的操作。eg:给数组中某一个元素加锁。 ConcurrentHashMap有个Entry数组,数组中每个元素是一个链表,也是一个Segment(分段锁)。当put元素时,不是对整个hashMap加锁(hashTable是),而是通过hashCode知道它在哪一分段,然后对这个分段加锁。 注:这不是具体的锁,是一种锁设计。 |
偏向锁、轻量级锁、重量级锁 |
这3种锁是synchronized锁的状态,通过对象监视器在对象头中的字段区分。 eg:synchronized锁升级过程 1.偏向锁:一段同步代码一直被一个线程访问,那么该线程自动获取这个锁(降低获取锁的代价) 2.轻量级锁:当前锁为偏向锁,且被另一个线程访问时,偏向锁升级为轻量级锁,其他线程通过自旋尝试获取锁,不会阻塞其他线程 3.重量级锁:当前锁为轻量级锁,其他线程自旋到一定次数还没获取到锁,轻量级锁升级为重量级锁,阻塞其他线程。 |
可重入锁 |
同一线程,在外层方法获取到锁之后,进入内层方法自动获取锁。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)