去大厂面试被问懵了...Java面试官的多线程与锁追魂夺命10连问,80%的人都答不上来

88 篇文章 10 订阅
6 篇文章 0 订阅

趁着金三银四的季节,想着去大厂面试试一下,说不准咱遇到一个大冤种面试官成功上岸了呢。谁知道一上来面试官简历都没看,直接给我来了套并发多线程组合拳,直接把我给干懵了,大佬是我不配,打扰了。在这里插入图片描述

回来后我把面试官的问题复盘了一下,现在就分享给大家,希望对大家面试有所帮助。当然,如果觉得博主总结的不错的话,希望能给个三连支持一下,让更多的人看到,谢谢啦。另外我总结了最新的面试题文档,包含spring、并发、数据库、Redis、分布式、dubbo、JVM、微服务等方面总结,大家可以看下方这篇文章。

面试必拿下!Java程序员面试95%被问到的面试题总结

1、什么是进程?什么是线程?(一个简单的暖场题)

进程是操作系统分配资源的最小单元
线程是操作系统调度的最小单元,线程隶属于进程。
一个程序至少有一个进程,一个进程至少有一个线程。

2、JAVA如何开启线程?怎么保证线程安全?

如何开启线程?
1、继承Thread类,重写run方法。
2、实现Runnable接口,实现run方法。
3、实现Callable接口,实现call方法。通过FutureTask创建一个线程,获取到线程执行的返回值。
4、通过线程池来开启线程。

怎么保证线程安全?
加锁: 1、 JVM提供的锁, 也就是Synchronized关键字。
2、 JDK提供的各种锁 Lock。

3、 Volatile和Synchronized有什么区别?Volatile能不能保证线程安全?DCL(DoubleCheck Lock)单例为什么要加Volatile?

1、Synchronized关键字,用来加锁。 Volatile只是保持变量的线程可见性。通常适用于一个线程写,多个线程读的场景。
2、不能。Volatile关键字只能保证线程可见性, 不能保证原子性。
3、Volatile防止指令重排。在DCL中,防止高并发情况下,指令重排造成的线程安全问题。

4、JAVA线程锁机制是怎样的?偏向锁、轻量级锁、重量级锁有什么区别?锁机制是如何升级的?

1、JAVA的锁就是在对象的Markword中记录一个锁状态。无锁,偏向锁,轻量级锁,重量级锁对应不同的锁状态。
2、JAVA的锁机制就是根据资源竞争的激烈程度不断进行锁升级的过程。
3、在这里插入图片描述

5、谈谈你对AQS的理解。AQS如何实现可重入锁?

1、AQS是一个JAVA线程同步的框架。是JDK中很多锁工具的核心实现框架。
2、 在AQS中,维护了一个信号量state和一个线程组成的双向链表队列。其中,这个线程队列,就是用来给线程排队的,而state就像是一个红绿灯,用来控制线程排队或者放行的。 在不同的场景下,有不用的意义。
3、在可重入锁这个场景下,state就用来表示加锁的次数。0标识无锁,每加一次锁,state就加1。释放锁state就减1。

6、Java中的volatile 变量有什么作用?

1、确保多线程可见性
2、禁止指令重排序
在这里插入图片描述

7、Lock接口(Lock interface)是什么?对比synchronized它有什么优势?

Lock接口比同步方法和同步块提供了更具扩展性的锁操作。

Lock是synchronized的扩展版,Lock提供了无条件的、可轮询的(tryLock方法)、定时的(tryLock带参方法)、可中
断的(lockInterruptibly)、可多条件队列的(newCondition方法)锁操作。另外Lock的实现类基本都支持非公平锁(默
认)和公平锁,synchronized只支持非公平锁,当然,在大部分情况下,非公平锁是高效的选择。

8、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样
别人想拿这个数据就会阻塞直到它拿到锁。Java里面的同步原语synchronized关键字的实现是悲观锁。

乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会
判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。在Java中原子变量类就是使用了乐观锁的
一种实现方式CAS实现

乐观锁的实现方式:

  • 使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标识,不一致时可以采取丢弃和再次
    尝试的策略。
  • java中的Compare and Swap即CAS ,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更
    新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

9、有三个线程T1,T2,T3,怎么确保它们按顺序执行?

1、先启动最后一个(T3调用T2,T2调用T1)

package com.tuling;
public class Testt {
     static Testt t=new Testt();
     class T1 extends Thread{
      @Override
     public void run() {
       //T3线程中要处理的东西
     System.out.println("T1线程执行");
    }
}
     class T2 extends Thread{
      @Override
      public void run() {
        //T3线程中要处理的东西
      System.out.println("T2线程执行");
      t.new T1().start();
    }
}
     class T3 extends Thread{
        @Override
       public void run() {
         //T3线程中要处理的东西
       System.out.println("T3线程执行");
       t.new T2().start();
     }
}
     public static void main(String[] args) {
        t.new T3().start();
     }
}

2.可以用线程类的join()方法在一个线程中启动另一个线程,另一个线程完成

10、你对线程优先级的理解是什么?

每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这
个实现是和操作系统相关的(OS dependent)。我 们可以定义线程的优先级,但是这并不能保证高优先级的线程会
在低优先级的线程前执行。线程优先级是一个 int 变量(从 1-10),1 代表最低优先级,10 代表最高优先级。

java 的线程优先级调度会委托给操作系统去处理,所以与具体的操作系统优先级有关,如非特别需要,一般无需设
置线程优先级。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值