面试 Java 并发编程八股文十问十答第六期

2024-03-13 13:12

本文主要是介绍面试 Java 并发编程八股文十问十答第六期,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

面试 Java 并发编程八股文十问十答第六期

作者:程序员小白条,个人博客

相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新!

⭐点赞⭐收藏⭐不迷路!⭐

1)synchronized 和 ReentrantLock 区别是什么?

  • 锁的获取方式:synchronized 是隐式锁,通过在方法或代码块上加上 synchronized 关键字来获取锁,而 ReentrantLock 是显式锁,需要通过调用 lock() 方法来获取锁。
  • 锁的释放方式:synchronized 在代码块执行完毕或方法返回时会自动释放锁,而 ReentrantLock 需要在 finally 块中显式调用 unlock() 方法来释放锁,确保锁的释放。
  • 可重入性:ReentrantLock 是可重入锁,同一个线程可以多次获取同一把锁,而 synchronized 也是可重入的,但是要求是同一个线程在持有锁的情况下才能再次获取锁。
  • 等待可中断:ReentrantLock 提供了可中断的获取锁的方式,通过调用 lockInterruptibly() 方法可以使等待锁的线程响应中断,而 synchronized 则不支持中断。
  • 公平性:ReentrantLock 可以通过构造函数指定是否是公平锁,即按照线程的请求顺序来获取锁,默认是非公平锁,而 synchronized 是非公平锁。
  • 扩展性:ReentrantLock 提供了更多的功能,比如可定时的、可轮询的、可中断的获取锁的方式,以及公平锁的支持等,而 synchronized 的功能相对较少。

2)volatile 关键字的作用

volatile 关键字的作用是保证变量的可见性和禁止指令重排序。具体来说,volatile 修饰的变量在多线程环境下的写操作会立即刷新到主内存,并且在读操作时会从主内存中获取最新的值,而不是使用线程私有的缓存。这样可以保证不同线程之间对该变量的操作是正确可见的。

此外,volatile 修饰的变量也禁止了指令重排序优化,保证了特定操作的执行顺序。这对于一些需要保证顺序性的场景非常重要,例如双重检查锁定(Double-Checked Locking)中的单例模式。

需要注意的是,volatile 并不能保证原子性,即不能保证多个线程同时执行的复合操作的原子性,如果需要保证原子性,需要使用其他的同步机制,比如使用 synchronized 或者使用原子类。

3)Java 中能创建 volatile 数组吗?

在 Java 中,不能直接创建 volatile 数组。volatile 关键字只能修饰类的成员变量或者类的静态变量,不能直接修饰数组。如果需要将整个数组作为一个原子性操作进行处理,可以使用 AtomicIntegerArray 或者 AtomicReferenceArray 等原子类来代替。这些原子类提供了对数组元素的原子性操作,可以满足多线程环境下对数组的需求。

4)volatle 变量和 atomic 变量有什么不同?

  • 可见性:volatile 变量保证了可见性,即对一个 volatile 变量的写操作对于其他线程是可见的,而 atomic 变量也保证了可见性。
  • 原子性:atomic 变量提供了一些原子性操作,例如 atomicInteger 的自增和自减操作是原子的,而 volatile 变量本身并不保证原子性。
  • 内存屏障:atomic 变量通过使用底层的 CAS(Compare and Swap)操作来保证原子性,这会涉及到底层的内存屏障操作,而 volatile 变量也会使用内存屏障来保证可见性。
  • 顺序性:atomic 变量提供了一些有序性保证的方法,例如使用 AtomicInteger 的 getAndSet() 方法可以保证写操作的顺序性,而 volatile 变量本身并不提供有序性保证。

5)volatile 能使得一个非原子操作变成原子操作吗?

volatile 不能使得一个非原子操作变成原子操作。volatile 只能保证可见性和禁止指令重排序,它并不能保证多个操作的原子性。如果需要保证多个操作的原子性,需要使用其他的同步机制,例如使用 synchronized 或者使用原子类。

6)volatile 修饰符的有过什么实践?

  • 保证变量的可见性:使用 volatile 修饰共享变量,可以确保对该变量的写操作对其他线程是可见的,从而实现线程间的通信。
  • 双重检查锁定(Double-Checked Locking):在单例模式中,使用 volatile 修饰单例对象的引用,可以确保在多线程环境下创建单例对象的安全性。
  • 控制循环条件:在某些情况下,使用 volatile 修饰循环条件可以实现线程之间的同步和协作,例如在一个线程中改变循环条件的值,从而使其他线程退出循环。
  • 实现轻量级的同步:相比于 synchronized,volatile 修饰符的开销更小,适用于一些对性能要求较高的场景,例如在一些读多写少的情况下,可以使用 volatile 修饰共享变量来实现轻量级的同步。

7)synchronized 和 volatile 的区别是什么?

  • 功能:synchronized 用于实现线程的互斥同步,保证同一时刻只有一个线程可以执行被 synchronized 修饰的代码块或方法;而 volatile 用于保证变量的可见性和禁止指令重排序。
  • 用法:synchronized 通过在代码块或方法上加上 synchronized 关键字来获取锁,而 volatile 通过修饰变量来实现可见性和禁止指令重排序。
  • 原子性:synchronized 可以保证代码块或方法的原子性,即同一时刻只有一个线程可以执行,而 volatile 本身并不保证原子性。
  • 内存屏障:synchronized 使用内存屏障来保证可见性和有序性,而 volatile 也使用内存屏障来保证可见性和禁止指令重排序。
  • 适用范围:synchronized 适用于复杂的线程同步场景,可以保证线程安全;而 volatile 适用于简单的变量共享场景,可以保证变量的可见性。

8)什么是不可变对象,它对写并发应用有什么帮助?

不可变对象是指创建后不可被修改的对象。它对写并发应用有很大的帮助,因为不可变对象不会发生状态的改变,所以多个线程可以同时访问不可变对象而不需要额外的同步控制。这样可以避免了线程之间的竞争和冲突,提高了并发性能和线程安全性。

不可变对象的特点是:对象创建后状态不可变、属性都是 final 和 private、没有提供修改状态的方法。常见的不可变对象有 String、Integer、BigDecimal 等。

9)Java Concurrency API 中的 Lock 接口(Lock interface)是什么?对比同步它有什么优势?

  • 可中断性:Lock 接口提供了可以响应中断的获取锁的方式,通过 lockInterruptibly() 方法可以使等待锁的线程响应中断。
  • 公平性:Lock 接口可以实现公平锁,即按照线程的请求顺序来获取锁。
  • 条件变量:Lock 接口提供了 Condition 接口,可以通过 Condition 实现线程的等待和唤醒操作,实现更灵活的线程同步。
  • 可重入性:Lock 接口和 synchronized 关键字一样,都支持可重入性,同一个线程可以多次获取同一把锁。
  • 灵活性:Lock 接口提供了更多的功能,例如可定时的、可轮询的、可中断的获取锁的方式,以及公平锁的支持等。

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

  • 乐观锁:乐观锁的思想是假设在并发情况下不会发生冲突,所以不加锁直接进行操作,当发生冲突时再进行处理。乐观锁的实现方式包括版本号机制、CAS(Compare and Swap)操作等。
  • 悲观锁:悲观锁的思想是假设在并发情况下会发生冲突,所以在操作前先加锁,确保同一时刻只有一个线程可以访问共享资源。悲观锁的实现方式包括 synchronized 关键字、Lock 接口等。

乐观锁和悲观锁的选择取决于具体的应用场景和需求。乐观锁适用于读多写少的情况,可以提高并发性能;而悲观锁适用于写多读少的情况,可以保证数据的一致性和安全性。在实际应用中,可以根据具体的业务需求选择合适的锁机制。

开源项目地址:https://gitee.com/falle22222n-leaves/vue_-book-manage-system

前后端总计已经 800+ Star,1.5W+ 访问!

⭐点赞⭐收藏⭐不迷路!⭐

这篇关于面试 Java 并发编程八股文十问十答第六期的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/805002

相关文章

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例:

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.