面试题-多线程并发编程

基础知识

为什么要是使用并发编程

  • 提升多核CPU的利用率,一般来说一台主机上的会有多个CPU核心,我们可以创建多个线程,理论上讲操作系统可以将多个线程分配给不同的CPU去执行,每个CPU执行线程,这样就提高了CPU的使用效率,如果使用单线程就只能有一个CPU核心被使用。
  • 比如当我们在网上购物时,为了提升响应速度,需要拆分,减库存,生成订单等等这些操作。就可以进行拆分进行多线程的技术完成,面对复杂业务模型,并行程序会比串行程序更适应业务需求,而并发编程更能吻合这种业务拆分。
  • 简单来说就是:

    • 充分利用多核CPU的计算能力。
    • 方便进行业务拆分,提升应用性能。

多线程应用场景

例如:迅雷多线程下载、数据库连接池、分批发送短信等等。

并发编程有什么缺点

并发编程的目的就是为了能提供程序的执行效率,提供程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、上下文切换、线程安全、死锁等等问题。

并发编程三个必要因素是什么?

  • 原子性:即一个不可再被分割的颗粒,操作要从头到尾一口气执行完毕,不能被其他操作所中断。
  • 可见性:一个线程对共享变量的修改,另一个线程能够立刻看到。
  • 有序性:程序执行的顺序按照代码的先后顺序执行。(处理器可能会对指令进行重排序)

Java程序中怎么保证多线程的运行安全的呢?

出现线程安全问题的原因一般都是三个原因:

  1. 线程切换带来的原子性问题;解决办法:使用多线程之间同步synchronized或者使用锁lock。
  2. 缓存导致的可见性问题;解决办法:synchronized、volatile、lock,可以解决可见性问题
  3. 编译优化带来的有序性问题;解决办法:happens-Before 规则可以解决有序性问题

并行并发、串行有什么区别?

  • 并发:多个任务在同一个CPU核上,按细分的时间片轮流交替执行,从宏观上看这些任务好像是同时进行似的(其实不是)
  • 并行:单位时间内,多个处理器或多核处理器同时处理多个任务,是真正意义上的“同时进行”。
  • 串行:有n个任务,由一个线程按顺序执行。由于任务、方法都在一个线程执行所以不存在线程不安全情况,也就不存在临界区的问题。
    做一个形象的比喻:
    并发 = 俩个人用一台电脑。
    并行 = 俩个人分配了俩台电脑。
    串行 = 俩个人排队使用一台电脑。

多线程的好处

可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其他的线程而不是等待,这样就大大提高了程序的效率。也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

多线程的劣势

  • 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多。
  • 多线程需协调和管理,所以需要CPU时间跟踪线程
  • 线程之间对共享资源的访问会相互影响,必须解决竞争使用共享资源的问题。

线程和进程的区别

  • 线程属于进程,线程是进程的一部分。线程不能脱离进程而存在
  • 一个进程中的多个线程可以共享一部分相同的资源,同时还拥有部分自己独有的资源例如程序计数器。而进程与进程之间一般是相互独立的,不存在内存资源共享的情况。
  • 一个进程中一个线程的崩溃可能会影响其他线程的运行,而一个系统中一个进程的崩溃,大部分情况并不会影响其他进程的长正常运行。

什么是上下文切换?

在我们平时的的多线程编程中,大部分情况下,我们的创建的线程数是大于我们主机电脑CPU的核心数的。而CPU的一个核心同一个时刻只能执行一个线程,为了能够让其他多余的线程也能被CPU所关照到。我们就需要让CPU轮流去指向这些多余的线程,给每个线程分配一个时间片。当一个线程的时间片被消耗完毕后,CPU就会让这个线程进入休眠状态,让已经进行准备运行状态的线程获得CPU的使用权。这个从一个线程切换到另外一个线程的过程,就叫做上下文切换。

守护线程和用户线程有什么区别呢?

  • 用户进程:就是我们平时windows电脑上前台所运行的QQ、微信程序,或者是Linux服务器上运行的Java jar服务。
  • 守护进程:而守护进程呢,则是依附其对应的用户进程而存在的。为其用户进程而服务,随着用户进程的消亡,而毁灭。

如何在Linux 上查找哪个线程cpu利用率最高?

  • 终端执行top命令,然后shift + p找出cpu利用率最高的进程pid号(如果是排查内存占用问题,则shift+m)
  • 根据上面拿到的pid好,执行top -H -p pid号,然后继续按下shift + p,找到cpu占有率最高的线程
  • 然后将获取到的线程pid号转换为16进制,使用jstack工具,jstack pid号 > /tmp/t.dat,如jstack 21324 > /tmp/t.dat
  • 然后vim刚才的文件,找到线程号对应的信息

什么是线程死锁

  • 死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程(线程)称为死锁进程(线程)。
  • 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。

你可能感兴趣的:(多线程并发编程java面试)