java多线程面试题

1、线程、进程和程序的概念

程序:只是一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体。

进程:是程序在某个数据集上的执行。进程是一个动态的实体,它有自己的生命周期。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消。反映了一个程序在一定的数据集上运行的全部动态过程。

线程:线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。

2、进程与线程的区别

1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;

2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线

3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;

4. 调度和切换:线程上下文切换比进程上下文切换要快得多

3、synchronized和lock的区别

 java多线程面试题

 

 

 

  1. 来源:
    lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;

  2. 异常是否释放锁:
    synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)

  3. 是否响应中断
    lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断;

  4. 是否知道获取锁
    Lock可以通过trylock来知道有没有获取锁,而synchronized不能;

  5. Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)

  6. 在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

  7. synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度,

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

1.互斥条件:一个资源每次只能被一个进程使用

2.请求与保持条件:一个进程因请求资源而阻塞时,对以获得的资源保持不放。

3.不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

5、死锁的避免与预防

死锁避免的基本思想:系统对进程发出每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。

  理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。只要打破四个必要条件之一就能有效预防死锁的发生:

  ● 打破互斥条件:改造独占性资源为虚拟资源,大部分资源已无法改造。

  ● 打破不可抢占条件:当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。

  ● 打破占有且申请条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。

  ● 打破循环等待条件:实现资源有序分配策略,对所有设备实现分类编号,所有进程只能采用按序号递增的形式申请资源。

死锁避免和死锁预防的区别:

  死锁预防是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现;而死锁避免则不那么严格的限制产生死锁的必要条件的存在,因为即使死锁的必要条件存在,也不一定发生死锁。死锁避免是在系统运行过程中注意避免死锁的最终发生。

6、线程同步

java多线程面试题

 

7、线程池

背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。

思路:提前创建多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

好处:

提高响应速度(减少了创建新线程的时间)

降低资源消耗(重复利用线程池中的资源,不需要每次都构建)

便于线程管理

  • corePoolSize:核心池的大小
  • maximumPoolSize:最大线程数
  • keepAliveTime:线程没有任务时最多保持多长时间后会终止

使用线程池

JDK 5.0起提供了线程池相关API:ExecutorService和Executors

ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

  • void execute(Tunnable command):执行任务/命令,没有返回值,一般用来执行Runnable
  • <T>Future<T>submit(Callable<T>task):执行任务,有返回值,一般用来执行Callable
  • void shutdown():关闭线程池

Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

 

上一篇:乐观锁与悲观锁


下一篇:多线程中 synchronized 锁升级的原理