Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • JAVA基础

  • 集合容器

  • Netty

  • JVM

  • JUC

    • 并发机制初识
    • JMM语义与重排
    • 多线程通信与编程应用
    • Lock并发锁原理
    • 并发容器与框架
    • 原子操作类
    • 并发工具类
    • 线程池
    • Executor框架
    • 并发编程实践
    • JUC面试
      • 一、Volatile和Synchronized有什么区别?Volatile能不能保证线程安全?DCL单例为什么要加Volatile?什么是指令重排?
      • 二、JAVA锁机制是怎样的?偏向锁、轻量级锁、重量级锁有什么区别,如何升级?什么是CAS?
      • 三、谈谈对AQS的理解。AQS如何实现可重入锁?
      • 四、有A,B,C三个线程,如何保证三个线程同时执行?如何在并发情况下保证三个线程依次执行?如何保证三个线程有序交错进行?
      • 五、为什么wait,notify方法不定义在thread中?
  • Java
  • JUC
phan
2023-05-16
目录

JUC面试

# JUC面试

# 一、Volatile和Synchronized有什么区别?Volatile能不能保证线程安全?DCL单例为什么要加Volatile?什么是指令重排?

1.Synchronized是关键字,用于加锁。而Volatile是用来保证变量的线程可见性(每次线程访问该变量得到的都是最新的值),但是不具有原子性,因此并不能保证线程安全,一般用于一个线程写,多个线程读的场景。

2.DCL单例加入Volataile目的是防止指令重排,造成高并发场景下的线程安全问题 。

3.指令重排是指JVM为了调高性能,在不影响结果的条件下,不按照编码的顺序执行语句。

# 二、JAVA锁机制是怎样的?偏向锁、轻量级锁、重量级锁有什么区别,如何升级?什么是CAS?

1.JAVA的锁就是在对象Markword中记录的一个锁状态,并根据资源竞争激烈程度,不断升级锁,分为无锁,偏向锁,轻量级锁,重量级锁。

2.偏向锁可以理解为锁偏向于第一个获取它的线程,创建的第一个线程则上偏向锁,当该进程下次再想获得锁时,不需要再获得锁;若存在竞争则升级为轻量级锁,通过CAS 避免了使用互斥量的开销,其他的进程不断自旋等待更新;当有非常多自旋的进程时(存在线程之间的同时竞争,CAS失败),JVM上报操作系统升级为重量级锁,每一步都让操作系统来管理,效率比较低。

Snipaste_2022-02-15_22-07-24

可以理解为偏向锁相当于只有一个线程在临界区;轻量级锁相当于有多个线程交替访问临界区,你用完给我,我用完给你;而重量级锁相当于是同时有多个线程想要进入临界区。

3.锁又可以分为悲观锁(synchronized)和乐观锁(CAS),前者性能比较差。CAS就是通过比较和交换,有三个操作数V,A和B,要进行修改操作时,先把要写入内存地址V的值取出来赋给A(旧预期值),然后把修改后结果赋给B,当要把B写入V时,要检查A和当前V地址的值是否相同,若相同则写入B,否则重复以上操作更新A,B重新写入。

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

1.AQS是一个JDK提供的显示锁的框架,Lock类操作通过内部类Sync类来实现,而Sync类又继承了AQS类;在AQS类当中,有一个双向线程队列,还有一个state信号量,通过该信号量来控制线程排队放行的。不同场景下有不同意义。

2.可重入锁是指对同一个线程而言,该线程可以lock()多次获得多个锁,一般适用于线程需要多次进入临界区的场景。在可重入锁场景下,state用来记录锁的计数值,每lock()一次就加1,release()则减一,直到减为0其他线程才能进入临界区。

# 四、有A,B,C三个线程,如何保证三个线程同时执行?如何在并发情况下保证三个线程依次执行?如何保证三个线程有序交错进行?

1.线程同时执行(或者一个线程等多个线程)使用CountDownLatch,初始时先设定一个计数器,每当一个任务执行完则CountDownLatch.countDown()使计数器减一,当计数器减为0时,被CountDownLatch.await()阻塞的线程唤醒,执行await()往下的代码。

2.依次执行可以使用volataile变量来控制;有序交错执行都可以使用Semaphore信号量,B要在A执行完后才执行,则A执行完后需要release()释放B的信号量,B中acquire()获得信号量后才能执行往下的代码。

# 五、为什么wait,notify方法不定义在thread中?

因为java的锁是对象级的,对象通过线程获得锁,锁是属于对象的。如果定义在thread中,那么线程等待的是哪的锁就不是很明确。

编辑 (opens new window)
#面试
上次更新: 2023/12/15, 15:49:57
并发编程实践

← 并发编程实践

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式