1 Star 0 Fork 31

阿明 / Ebooks

forked from Java精选 / Ebooks 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
2021年Java并发面试题大汇总附答案.md 9.90 KB
一键复制 编辑 原始数据 按行查看 历史

2021年Java并发面试题大汇总附答案

全部面试题答案,更新日期:01月30日,直接下载吧!

下载链接:高清500+份面试题资料及电子书,累计 10000+ 页大厂面试题 PDF

Java 并发

题1:Java 中 AQS 核心思想是什么?

AQS核心思想是如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用。

题2:Java 中无锁队列的原理是什么?

SynchronousQueue队列是无锁队列,其内部是使用CAS自旋操作保证线程安全。

题3:Java 中 volatile 和 synchronized 有什么区别?

volatile关键字能够保证数据的可见性,但不能保证数据的原子性。

synchronized关键字既能够保证数据的可见性,又能够保证数据的原子性,即保证资源的同步。

volatile关键字只能用于修饰变量,而synchronized关键字可以修饰方法以及代码块。

题4:ConcurrentHashMap 和 Hashtable 有什么区别?

ConcurrentHashMap和Hashtable都可以用于多线程的环境,但当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。

HashTable的任何操作都会把整个表锁住,是阻塞的。好处是:总能获取最实时的更新,比如说线程A调用putAll()写入大量数据,期间线程B调用get(),线程B就会被阻塞,直到线程A完成putAll(),因此线程B肯定能获取到线程A写入的完整数据。坏处是所有调用都需要排队,效率较低。

ConcurrentHashMap是设计为非阻塞的。在更新时会局部锁住某部分数据,但不会把整个表都锁住。同步读取操作则是完全非阻塞的。好处是在保证合理的同步前提下,效率很高。坏处是:严格来说,读取操作不能保证反映最近的更新。例如线程A调用putAll()写入大量数据,期间线程B调用get(),则只能get()到目前为止已经顺利插入的部分数据。

JDK8的版本,与JDK6的版本有很大差异。实现线程安全的思想也已经完全变了,它摒弃了Segment(分段锁)的概念,而是启用了一种全新的方式实现,利用CAS算法。它沿用了与它同时期的HashMap版本的思想,底层依然由数组+链表+红黑树的方式思想,但是为了做到并发,又增加了很多复制类,例如TreeBin、Traverser等对象内部类。CAS算法实现无锁化的修改至操作,他可以大大降低锁代理的性能消耗。这个算法的基本思想就是不断地去比较当前内存中的变量值与你指定的一个变量值是否相等,如果相等,则接受你指定的修改的值,否则拒绝你的操作。因为当前线程中的值已经不是最新的值,你的修改很可能会覆盖掉其他线程修改的结果。

题5:创建线程池的有几种方式?

newCachedThreadPool

创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,如果没有可回收线程,则新建线程。

newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。

newSingleThreadExecutor

创建一个单线程化的线程池,它只会唯一的工作线程来执行任务,保证所有任务按照指定执行。

题6:Java 中为什么代码会重排序?

在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是不是想怎么排序就怎么排序,需要满足以下两个条件:

1)在单线程环境下不能改变程序运行的结果; 2)存在数据依赖关系的不允许重排序

需要注意的是:重排序不会影响单线程环境的执行结果,但是会破坏多线程的执行语义。

题7:什么是协程?

协程(Coroutine):是单线程下的并发,又称微线程,纤程。简单理解就是线程中的线程。

优点

轻量,创建成本小,降低了内存消耗

用户态调度,减少了 CPU 上下文切换的开销,提高了 CPU 缓存命中率

减少同步加锁,提高了性能

可以用同步思维写异步代码

缺点

在协程执行中不能有阻塞操作,否则整个线程被阻塞

不擅长处理 CPU 密集型

适用场景

高性能要求,考虑牺牲公平性换取吞吐量

IO 密集型任务

Generator 式的流式计算

题8:Java 中 ++ 操作符是线程安全的吗?

1)如果是方法内定义的局部变量,因为每个方法栈是线程私有的,所以一定是线程安全的。

2)如果是类的成员变量,++i就是非线程安全的,这是因为++i相当于i=i+1。

实现线程安全可以使用synchronize关键字修饰提供同步或使用AtomicInteger原子操作类,因++i同步体比较小,可以使用自旋CAS的AtomicInteger类实现线程安全。

注意:因为volatile只能保证可见性,不能保证原子性,所以volatile不能解决这个线程安全存在的问题。

AtomicInteger保证线程安全

在JDK1.5版本之后,Java程序才可以使用CAS操作,该操作由sun.misc.Unsafe类中compareAndSwapInt()和compareAndSwapLong()等几个方法包装提供,虚拟机编译出来的结果就是一条平台相关的处理器CAS指令。

Unsafe类中getUnsafe()方法中限制了只有启动类加载器Bootstrap ClassLoader加载的Class才能访问它,因此Unsafe类不提供给用户程序调用,如果不使用反射机制的话只能通过其他的Java API来使用它,比如JUC包中AtomicInteger类,其中incrementAndGet()等方法都使用了Unsafe类的CAS操作。

JDK1.8源码如下:

public final int incrementAndGet() {
	return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int getAndAddInt(Object o, long offset, int delta) {
	int v;
	do {
		v = getIntVolatile(o, offset);
	} while (!compareAndSwapInt(o, offset, v, v + delta));
	return v;
}

通过源码可以看出AtomicInteger类是通过自旋CAS实现了线程安全的数量变化。

题9:什么是不可变对象,对写并发应用有什么帮助?

不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects)。

不可变对象的类即为不可变类(Immutable Class)。Java平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。

不可变对象天生是线程安全的。它们的常量(域)是在构造函数中创建的。既然它们的状态无法修改,这些常量永远不会变。

不可变对象永远是线程安全的。

只有满足如下状态,一个对象才是不可变的。

1)它的状态不能在创建后再被修改; 2)所有域都是final类型; 3)被正确创建(创建期间没有发生this引用的逸出)。

题10:什么是可重入锁(ReentrantLock)?

举例来说明锁的可重入性

public class UnReentrant{
    Lock lock = new Lock();
    public void outer(){
        lock.lock();
        inner();
        lock.unlock();
    }
    public void inner(){
        lock.lock();
        //do something
        lock.unlock();
    }
}

outer中调用了inner,outer先锁住了lock,这样inner就不能再获取lock。其实调用outer的线程已经获取了lock锁,但是不能在inner中重复利用已经获取的锁资源,这种锁即称之为 不可重入可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。

synchronized、ReentrantLock都是可重入的锁,可重入锁相对来说简化了并发编程的开发。

题11:为什么使用-executor-框架

题12:java-中的-readwritelock-是什么

题13:什么是-cas

题14:公平锁和非公平锁有什么区别

题15:多线程实现的方式有几种

题16:线程池的原理是什么

题17:什么是-threadlocal-变量

题18:callable-和-runnable-有什么区别

题19:synchronousqueue-队列的大小是多少

题20:什么是线程局部变量

题21:进程与线程之间有什么区别

题22:并发和并行有什么区别

题23:什么是-aba-问题

题24:java-中-aqs-底层原理是什么

题25:为什么-wait()-和-notify()-方法要在同步块中调用

大厂面试题

大厂面试题

大厂面试题

Java
1
https://gitee.com/AminDev/ebooks.git
git@gitee.com:AminDev/ebooks.git
AminDev
ebooks
Ebooks
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891