Java面试题之并发篇

本文详细阐述了产生死锁的四个必要条件,提供了解决死锁的方法(如指定获取锁顺序),介绍了如何通过jstack检查死锁,以及synchronized锁在JDK1.6以后的优化过程,包括偏向锁、轻量级锁、重量级锁、自旋锁和自适应锁,以及锁消除的概念。
摘要由CSDN通过智能技术生成

1、产生死锁的四个必要条件

  1. 互斥条件:一个资源每次只能被一个线程使用
  2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放
  3. 不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系

2、如何避免死锁

指定获取锁的顺序,举例如下:

  1. 比如某个线程只有获得A锁和B锁才能对某资源进行操作,在多线程条件下,如何避免死锁?
  2. 获得锁的顺序是一定的,比如规定,只有获得A锁的线程才有资格获取B锁,按顺序获取锁就可
    以避免死锁!!!

3、如何查看死锁

可以通过jstack 命令来进行查询,jstack命令中会显示发生了死锁的线程

4、synchronized的锁升级过程是怎样的?

从JDK1.6版本之后,synchronized本身也在不断优化锁的机制,有些情况下他并不会是一个很重量
级的锁了。优化机制包括自适应锁、自旋锁、锁消除、锁粗化、轻量级锁和偏向锁。
锁的状态从低到高依次为无锁->偏向锁->轻量级锁->重量级锁,升级的过程就是从低到高,降级在
一定条件也是有可能发生的。
偏向锁】:在锁对象的头部中记录一下当前获取到该锁的线程ID,下次如果该线程又来获取该锁就可以直接获取了。也就是支持锁可重入。
轻量级锁】:当两个或以上的线程交替获取锁,但没有在对象上并发的获取锁时,偏向锁升级为轻量级锁。线程采用cas的自旋方式尝试获取该锁,避免阻塞线程造成的cpu在用户态和内核态间转换的消耗。
重量级锁】:当两个或以上的线程并发的在同一个对象进行同步时,避免无用的自选消耗cpu,轻量级锁会升级成重量级锁。

自旋锁:由于大部分时候,锁被占用的时间很短,共享变量的锁定时间也很短,所有没有必要挂起
线程,用户态和内核态的来回上下文切换严重影响性能。自旋的概念就是让线程执行一个忙循环,
可以理解为就是啥也不干,防止从用户态转入内核态,自旋锁可以通过设置-XX:+UseSpining来开
启,自旋的默认次数是10次,可以使用-XX:PreBlockSpin设置。
自适应锁:自适应锁就是自适应的自旋锁,自旋的时间不是固定时间,而是由前一次在同一个锁上
的自旋时间和锁的持有者状态来决定。
锁消除:锁消除指的是JVM检测到一些同步的代码块,完全不存在数据竞争的场景,也就是不需要
加锁,就会进行锁消除。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值