线程的生命周期和锁的过程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

Java 线程既然能够创建,那么也势必会被销毁,所以线程是存在生命周期的,了解一下线程的生命周期


一、线程状态

线程一共有 6 种状态
(NEW、RUNNABLE、BLOCKED、WAITING、TIME_WAITING、TERMINATED)

1. new : 初始状态,线程被构建,还没有调用start方法。
2. runnable:运行状态,线程中把操作系统中的就绪和运行状态统一称为 运行中
3. blocked: 阻塞状态,表示线程进入等待状态,因为某种原因放弃了CPU的使用权
4. time_waiting:超时等待状态,超时以后自动返回
5. terminated:终止状态,表示当前线程执行完毕
等待阻塞: 运行的线程执行wait方法,jvm会把当前线程放入等待队列
同步阻塞: 运行的线程在获取对象的同步锁时,若该同步锁被其他线程占用了,那么jvm会把当前线程放入锁池中
其他阻塞: 运行线程执行sleep或者join方法,或者发出i/o请求时,jvm会把当前线程设置为阻塞状态
                   当sleep结束,join线程终止,io处理完毕线程恢复

在这里插入图片描述

二、锁

1.偏向锁

大部分情况下,锁不仅仅不存在多线程竞争,而是总是由同一个线程多次获得,
为了让线程获取锁的代价更低,就引入偏向锁的概念。

当一个线程访问加了同步锁的代码块时,会在对象头中存储当前线程ID,后续这个线程进入和退出
这段加了同步锁的代码块时,不需要多次加锁和释放锁。

而是直接比较对象头里面是否存储了指向当前线程的偏向锁。如果相等表示偏向锁是偏向当前线程的
就不需要再尝试获取锁了

2.轻量级锁

1. 线程在自己的栈桢中创建锁记录 LockRecord
2. 将锁对象的对象头中的MarkWord复制到线程刚刚创建的锁记录中
3. 将锁记录中的owner指针指向锁对象
4. 将锁对象的对象头的MarkWord替换为指向锁记录的指针

自旋锁

轻量级锁在加锁过程中用到了 自旋锁

就是指当有另一个线程来竞争锁时,这个线程会在原地等待,而不是阻塞,
直到那个获得锁的线程释放锁之后,这个线程就可以立马获得锁。

注意:锁在原地循环的时候,消耗CPU,所以适用于那些同步代码块执行很快的场景

自适应自旋锁

自适应意味着自选的次数不是固定不变的,而是根据前一次在同一个锁上自旋的时间以及
锁的拥有者的状态来决定的

如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,
那么虚拟机就会认为这次自选也是很有可能再次成功,进而等待时间会持续更长的时间。
如果对于某个锁,自旋很少成功获得过,那在以后尝试获取这个锁时可能省略掉自旋的过程
直接阻塞

3. 重量级锁

每一个java对象都有一个监视器 monitor 关联,我们可以把它理解成一把锁,
当一个线程想执行一段被 synchronized 修饰的方法或者代码块时,
该线程得先获取到synchronized 修饰对象对应的 monitor。

monitor 依赖操作系统的互斥锁来实现的,线程被阻塞后便进入内核调度状态,
系统在用户态和内核态之间来回切换

在这里插入图片描述

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值