开篇介绍

大家好,公众号【Java极客思维】近期会整理一些Java高频面试题分享给小伙伴,也希望看到的小伙伴在找工作过程中能够用得到!本章节主要针对Java一些多线程高频面试题进行分享。

通知:公众号【Java极客思维】正在送书福利活动,关注公众号并参加福利活动吧!只有参与了本次活动的小伙伴才能够参与年底的大福利,不要错过呀~

Q1:

什么是CAS算法?

CAS(compare and swap)的缩写。

Java利用CPU的CAS指令,同时借助JNI来完成对Java的非阻塞算法,实现原子操作(其实就是自旋操作,不断循环,直到成功)。其它原子操作都是利用类似的特性来完成的。

CAS有三个关键操作值:内存值V、 预期值A 、 要修改的值B 。

当且仅当 预期值A 和 内存值V 一致时,才会将 内存值V 内容修改为 B,否则将什么都不做。

CAS的缺点也很明显:

在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,但是却又一直更新不成功,一直在循环(自旋),那么会给CPU带来很大的压力。

CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,这样就不得不使用synchronized关键字进行同步操作了。

比如线程A端了一杯水放在桌子上,但是被其他事调度走了,并且释放了锁,此时线程B经过,看到桌子上的水,端起来喝了半杯,然后又给打满一杯水放在桌子上。此时虽然还是一杯水,但是杯中的水不再是原来的那杯水了,而线程A也忙完了,回头来看到桌子上还是一杯水,但是不知道水已经被替换过了。这就是典型的ABA问题,还有很多类似的场景。这种情况对依赖过程值的情景的运算结果影响很大。这是CAS机制最大的问题所在。

  • CPU开销过大

  • 不能保证代码块的原子性

  • ABA问题

Q2:

什么是AQS?

AQS(AbstractQueuedSynchronizer)

AQS是JDK下提供的一套用于实现基于FIFO等待队列的阻塞锁和相关的同步器的一个同步框架。这个抽象类被设计作为一些可用原子int值来表示状态的同步器的基类。

如果有看过类似CountDownLatch类的源码实现,会发现其内部有一个继承了AbstractQueuedSynchronizer的内部类Sync。可见CountDownLatch是基于AQS框架来实现的一个同步器。类似的同步器在JUC下还有不少(比如Semaphore)。

AQS的核心思想是基于volatile int state 这样的volatile变量,配合Unsafe工具对其原子性的操作来实现对当前锁状态进行修改。同步器内部依赖一个FIFO的双向队列来完成资源获取线程的排队工作。

AQS中的数据结构 - 节点和同步队列

节点加入到同步队列

首节点变化

Q3:

volatile关键字有什么用?

Java提供了volatile关键字来保证可见性。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主内存中,当有其他线程需要读取时,它会去内存中读取新值。主要的原理是使用了内存指令。

  • LoadLoad重排序:一个处理器先执行一个L1读操作,再执行一个L2读操作;但是另外一个处理器看到的是先L2再L1;

  • StoreStore重排序:一个处理器先执行一个W1写操作,再执行一个W2写操作;但是另外一个处理器看到的是先W2再W1;

  • LoadStore重排序:一个处理器先执行一个L1读操作,再执行一个W2写操作;但是另外一个处理器看到的是先W2再L1;

  • StoreLoad重排序:一个处理器先执行一个W1写操作,再执行一个L2读操作;但是另外一个处理器看到的是先L2再W1。

Q4:

描述一下volatile关键字对原子性、可见性以及有序性是如何保证的?

在volatile变量写操作的前面会加入一个Release屏障,然后再之后会加入一个Store屏障,这样就可以保证volatile写跟Release屏障之前的任何读写操作都不会指令重排,然后Store屏障保证了,写完数据之后,立马会执行flush处理器缓存的操作。

在volatile变量读操作的前面会加入一个Load屏障,这样就可以保证对这个变量的读取时,如果被别的处理器修改过了,必须得从其他处理器的高速缓存(或者主内存)中加载到自己本地高速缓存里,保证读到的是最新数据;在之后会加入一个Acquire屏障,禁止volatile读操作之后的任何读写操作会跟volatile读指令重排序。

与volatile读写内存屏障对比一下,是类似的意思。

Acquire屏障 其实就是 LoadLoad屏障 + LoadStore屏障;

Release屏障 其实就是 StoreLoad屏障 + StoreStore屏障。

Q5:

简述一下synchronized关键字的原理是什么?

synchronized是由JVM实现的一种实现互斥同步的方式,查看被synchronized关键字修饰过的程序块编译后的字节码会发现:被synchronized修饰过的程序块,在编译前后被编译器生成了monitorenter 和 monitorexit 两个字节码指令。

在虚拟机执行到 monitorenter 指令时,首先会尝试获取对象的锁:如果这个对象没有锁定,或者当前线程已经拥有了这个对象的锁,把锁的计数器 + 1;

当执行 monitorexit 指令时,将锁计数器 - 1;当计数器为0时,锁就被释放了。如果获取对象失败了,那当前线程就要阻塞等待,知道对象锁被另外一个线程释放为止。

Q6:

CountDownLatch 和 CyclicBarrier的区别?

  • CountDownLatch的计数器只能使用一次。而CyclicBarrierd的计数器可以使用reset()方法进行重置。所以CyclicBarrier能处理更为复杂的业务场景。比如如果计算发生错误,可以重置计数器,并让线程们重新计算一次。

  • CyclicBarrier还提供其他有用的方法,比如getNumberWaiting()方法可以获得CyclicBarrier阻塞的线程数量。isBroken() 方法可以用来知道阻塞的线程是否被中断。

  • CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。

  • CountDownLatch依靠一个外力(计数器、发令枪)来控制线程,而CyclicBarrier是相当于用本身来控制线程。举个例子:

    • CountDownLatch:有一个装满宝石的房间,门外有7把锁,然后有7个人要进入房间组成队伍A,还有另外7个人手里拿着钥匙组成队伍B,那么首先A组的7个人必须等到B组的7个人把钥匙送过来,然后把门外的7把锁分别打开之后,这A组的7个人才能够进入房间拿到宝石。

    • CyclicBarrier:有一个装满宝石的房间,门外也有7把锁,然后7个人必须到另外的一个房间,各自完成一个任务之后,这7个人才能够各自获得一把锁,完成任务之后,这7个人就能够打开那7把锁,进房间拿到宝石。

明天,会介绍多线程一些深入的知识,长按二维码关注我吧~

祝大家都能拿到心仪的offer!


点关注、不迷路

如果觉得文章不错,欢迎关注点赞收藏,你们的支持是我创作的动力,感谢大家。

如果文章写的有问题,请不要吝啬,欢迎留言指出,我会及时核查修改。

如果你还想更加深入的了解我,可以微信搜索「Java极客思维」进行关注。每天8:00准时推送技术文章,让你的上班路不在孤独,而且每月还有送书活动,助你提升硬实力!

Java面试专题-多线程(3)-原子操作的更多相关文章

  1. Java面试专题-多线程篇(2)- 锁和线程池

  2. Java面试09|多线程

    1.假如有Thread1.Thread2.Thread3.Thread4四条线程分别统计C.D.E.F四个盘的大小,所有线程都统计完毕交给Thread5线程去做汇总,应当如何实现? 把相互独立的计算任 ...

  3. Java面试专题-基础篇(1)

  4. Java面试专题-集合篇(2)

  5. java面试:多线程

    1.多线程 ​ 同步:发送一个指令需要等待返回才能发送下一条(完成一件事才能做下一件). ​ 异步:发送一个请求不需要等待返回,随时可以再发下一条(一次进行多个事件) 线程不安全根本原因是异步,对一个 ...

  6. Java面试——多线程面试题总结

    )两者都在等待对方所持有但是双方都不释放的锁,这时便会一直阻塞形成死锁. //存放两个资源等待被使用 public class Resource { public static Object obj1 ...

  7. Java面试系列

    如果你的面试简历是如下这样写的,请务必准备回答下面的所有问题. 面试职位:Java高级工程师 专业技能: (1)牢固掌握Java基础知识,如集合.并发.I/O等,并对Java源码有一定的研究. (2) ...

  8. Java面试:投行的15个多线程和并发面试题

    多线程和并发问题已成为各种 Java 面试中必不可少的一部分.如果你准备参加投行的 Java 开发岗位面试,比如巴克莱银行(Barclays).花旗银行(Citibank).摩根史坦利投资公司(Mor ...

  9. Java面试:投行的15个多线程和并发面试题(转)

    多线程和并发问题已成为各种 Java 面试中必不可少的一部分.如果你准备参加投行的 Java 开发岗位面试,比如巴克莱银行(Barclays).花旗银行(Citibank).摩根史坦利投资公司(Mor ...

随机推荐

  1. “3+3”看华为云FusionInsight如何引领“数据新基建”持续发展

    摘要:一个统一的现代化的数据基建需要三类架构来实践三种不同的应用场景. 近期,美国知名科技企业风投机构A16Z总结出一套通用的技术架构服务,分为以下三种场景. 一.数据基建架构全景 数据流向显示,左侧 ...

  2. 创建一个自定义名称的Ceph集群

    前言 这里有个条件,系统环境是Centos 7 ,Ceph 的版本为Jewel版本,因为这个组合下是由systemctl来进行服务控制的,所以需要做稍微的改动即可实现 准备工作 部署mon的时候需要修 ...

  3. 【芯片手册开发】Sil9136音频开发详细分析+源码实战

    目录 前言 参考 手册使用+实战 配置 Configuring Audio Using I2S 总结实现 前言 默认在开发了视频方面后 这方面的工作本来可以找技术支持拿个例程参考下,很快就可以的写出来 ...

  4. python3 多线程批量验证POC模板

    #coding:utf-8 import threading,Queue,sys,os class RedisUN(threading.Thread): def __init__(self,queue ...

  5. 企业级工作流解决方案(九)--微服务Tcp消息传输模型之客户端处理

    客户端启动 客户端启动主要做三件事情,1. 从配置文件读取服务调用配置,存储到全局对象中.2. 指定客户端编解码器工厂.3. 预连接,即预先建立与服务端的通信Chanel. [DependsOn(ty ...

  6. 厉害!这份阿里面试官 甩出的Spring源码笔记,GitHub上已经爆火

    前言 时至今日,Spring 在 Java 生态系统与就业市场上,面试出镜率之高,投产规模之广,无出其右.随着技术的发展,Spring 从往日的 IoC 框架,已发展成 Cloud Native 基础 ...

  7. 【老孟Flutter】自定义文本步进组件

    交流 老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com 欢迎加入Flutter交流群(微信:laomengit).关注公众号[老孟Flutter] ...

  8. pandas 生成html文档,支持可添加多个表

    如何通过pandas生成html格式?如何通过pandas生成html文件文件中包含多个表单Balance_64_data = pd.read_sql(Balance_64_sql,engine)df ...

  9. Mac电脑疑似中毒该怎么应对处理

    Mac电脑作为相对封闭的一个系统,它会中毒吗?如果有一天Mac电脑产生了疑似中毒或者遭到恶意不知名攻击的现象,那又应该如何从容应对呢?这些问题都是小编使用Mac系统一段时间后产生的疑惑,通过一番搜索研 ...

  10. 教你调节Boom 3D的3D音效强度,让音乐更带感

    Boom 3D的专业3D环绕技术,让用户能全身心地沉浸在立体音效中.无论是聆听音乐,还是观赏电影,立体音效都能为人们带来更加真实的听觉感触. 那么,Boom 3D的3D环绕功能到底能给用户带来怎样的体 ...