牛客java面试题总结版(三)

13.概括的解释下线程的几种可用状态。
官方版

  1. 新建( new ):新创建了一个线程对象。
  2. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取 cpu 的使用权 。
  3. 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。
  4. 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。阻塞的情况分三种:
    (一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。
    (二). 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁 被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。
    (三). 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。 当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。
  5. 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。
    在这里插入图片描述
    大神版:链接:https://www.nowcoder.com/questionTerminal/f665a4c853b841339e7181a0fdbacfa8
    来源:牛客网

操作系统线程的5种状态:

1.新建状态:
线程创建但没有启动
2.就绪状态:
线程处于可运行的状态,当线程获得CPU的时间片后会被执行,时间片耗尽或主动放弃当次时间片(yield方法)时再次进入就绪状态。
3.运行状态:
线程得到时间片被CPU执行
4.阻塞状态:
线程放弃CPU的时间片(一直到某个条件达成),主动进入阻塞的状态。
同步阻塞:线程由于尝试获得对象的同步锁但无法取得时,进入锁池,等待其他线程释放该对象的锁。
等待阻塞:线程主动放弃对对象上的锁的占用,进入等待对象通知的队列。指wait方法
其他阻塞:线程主动进入休眠状态,等待条件达成。指sleep、join方法或I/O请求。
5.终止状态:
线程任务结束或异常退出
Java线程定义的6种状态:

1.新建状态NEW:
线程创建,但没有启动
2.可运行状态(就绪状态)RUNNABLE: 代表线程正在运行或者不处于阻塞、等待状态的可以被运行的状态。线程创建后或脱离阻塞、等待状态后进入可运行状态。
3.阻塞状态BLOCKED:
代表线程尝试获得一个锁时无法对锁占用,进入阻塞状态;当该线程能够获得锁时脱离阻塞状态。
4.等待状态WAITING:
等待线程主动进入等待条件达成的状态,可以使用join、wait、sleep方法。
5.计时等待状态TIMED_WAITING:
等待状态添加计时器,当等待条件达成或计时器耗尽时脱离等待状态。
6.中断状态(终止状态)TERMINATED:
线程任务结束或手动设置中断标记

14.同步方法和同步代码块的区别是什么?
官方版:区别:
同步方法默认用this或者当前类class对象作为锁;
同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;
同步方法使用关键字 synchronized修饰方法,而同步代码块主要是修饰需要进行同步的代码,用 synchronized(object){代码内容}进行修饰;

15.在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?
官方版:监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。

大神版
https://www.nowcoder.com/questionTerminal/26fc16a2a85e49a5bd5fc2b5759dbbc2
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,但两者的实现细节不一样。本质都是对一个对象的监视器(monitor)进行获取,而这个获取过程是排他的,也就是同一时刻只能有一个线程获取到由synchronized所保护对象的监视器

代码块同步是使用monitorenter和monitorexit指令实现的。monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处,JVM要保证每个monitorenter必须有对应的monitorexit与之配对。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁。

16.什么是死锁(deadlock)?
官方版:所谓死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。死锁产生的4个必要条件:
互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。

可能产生死锁的情况
(1) 因为系统资源不足。
(2) 进程运行推进顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

如何预防与解除死锁
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。

17.如何确保N个线程可以访问N个资源同时又不导致死锁?
官方版
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值