多线程面试题

来源:互联网 发布:广西网络培训系统 编辑:程序博客网 时间:2024/06/05 05:33

1.创建线程有几种不同的方式?你喜欢哪一种?为什么?

2种方式:1:要么继承Thread:2: 要么实现Runable接口 ,并与Thread对象相关联

我更喜欢第二种方式:避免了单继承的局限性,同时能有更多的组合

2.概括地解释一下线程的几种可用状态?

创建状态

阻塞状态

运行状态

冻结状态

消亡状态

3.同步方法和同步代码块的区别是什么?

同步方法是粗粒度锁,同步方法所用的锁是this ,而静态同步方法所用 的 锁是类名.class,效率较低

同步代码块是细粒度锁,锁可以是任意对象,效率较同步方法高

4.在监视器内部,是如何做线程同步的?程序应该做哪种级别的同步?

监视器(锁)监视一块同步代码块,确保一次只有一个线程执行同步代码块。为了实现监视器的互斥功能,每一个监视器都和一个对象引用相关联线程在获取锁之前不允许执行同步代码
 java 还提供了显式监视器( Lock )和隐式监视器( synchronized )两种锁方案

5.什么是死锁?

两个或两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是这些线程都陷入了无限的等待中。

发生死锁的原因是嵌套同步代码块,而锁不同

6.如何确保N个线程可以访问N个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。
因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了
多线程产生死锁的四个必要条件:
  1. 互斥条件:一个资源每次只能被一个进程使用。
  2. 保持和请求条件:一个进程因请求资源而阻塞时,对已获得资源保持不放。
  3. 不可剥夺调教:进程已获得资源,在未使用完成前,不能被剥夺。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
只要破坏其中任意一个条件,就可以避免死锁,其中最简单的就是破环循环等待条件。按同一顺序访问对象,加载锁,释放锁

6.快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?

.什么是 fail-fast 机制?

fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception。

fail-fast会在以下两种情况下抛出ConcurrentModificationException

(1)单线程环境

集合被创建后,在遍历它的过程中修改了结构。

注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。

(2)多线程环境

当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改。


 fail-safe机制

fail-safe任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出ConcurrentModificationException

fail-safe机制有两个问题

(1)需要复制集合,产生大量的无效对象,开销大

(2)无法保证读取的数据是目前原始数据结构中的数据。