juc并发包的常用类、线程安全实现方式、锁机制及 JVM 优化策略

juc并发包的常用类、线程安全实现方式、锁机制及 JVM 优化策略

  • [1. juc包下的常用类:](#1. juc包下的常用类:)
  • [2. 怎么保证多线程安全:](#2. 怎么保证多线程安全:)
  • [3. Java中常用锁及使用场景:](#3. Java中常用锁及使用场景:)
  • [4. 线程同步的方法:](#4. 线程同步的方法:)
  • [5. Synchronized锁静态方法和普通方法的区别:](#5. Synchronized锁静态方法和普通方法的区别:)
  • [6. Synchronized和ReentrantLock的区别:](#6. Synchronized和ReentrantLock的区别:)
  • [7. 怎么理解可重入锁:](#7. 怎么理解可重入锁:)
  • [8. Synchronized锁升级过程:](#8. Synchronized锁升级过程:)
  • [9. JVM对Synchronized锁优化:](#9. JVM对Synchronized锁优化:)
  • [10. 参考](#10. 参考)

1. juc包下的常用类:

线程池:

  • ThreadPoolExecutor:最核心的线程池类,用于创建和管理线程池。
  • Executors:线程池工厂类,提供了一系列静态方法来创建不同类型的线程池。

并发集合类:

  • ConcurrentHashMap:线程安全的哈希表;分段锁技术,允许多个线程同时访问不同的段,提高了并发性能。
  • CopyOnWriteArrayList:线程安全的列表,适合读多写少的场景,写操作会创建一个新的底层数组,读操作仍然在旧数组上进行,实现读写分离。

同步工具类:

  • CountDownLatch:允许一个或多个线程等待其他一组线程完成操作后再继续执行。通过一个计数器来实现,初始化计数器N,线程完成任务调用countDown方法将计数器减1,直至为0。
  • CyclicBarrier:让一组线程相互等待,直至所有线程都到达某个屏障点后,再一起执行。适用于多个线程需协同工作。
  • Semaphore:信号量,用于控制同时访问某个资源的线程数量,它维护了一个许可计数器。

原子类:

  • AtomicInteger;
  • AtomicLong;
  • AtomicBoolean;
  • AtomicReference;

2. 怎么保证多线程安全:

  • synchronized关键字,同步代码块或方法;
  • volatile关键字,用于变量,确保所有线程看到的是该变量的最新值;
  • Lock接口和ReentrantLock类;
  • 原子类;
  • 线程局部变量;
  • 并发集合:ConcurrentHashMap,CopyOnWriteArrayList;
  • JUC工具类:CountDownLatch,CyclicBarrier

3. Java中常用锁及使用场景:

  • 内置锁(Synchronized),一般用在简单代码块、方法上
  • ReentrantLock,只能用在代码块上,中断、定时、公平锁、控制多个变量、复杂并发场景
  • 读写锁,读多写少
  • 乐观锁和悲观锁:乐观锁不加锁,用版本号或时间戳来实现,悲观锁在访问数据前就会加锁。
  • 自旋锁:不放弃CPU,循环检查锁是否可用,适合锁等待时间很短的情况,否则会过度消耗CPU资源

4. 线程同步的方法:

"同步"强调调用者是否等待结果,"异步"强调调用者可以继续做事不被阻塞。

  • Synchronized关键字
  • ReentrantLock关键字
  • volatile关键字
  • Atomic类

5. Synchronized锁静态方法和普通方法的区别:

  • 普通方法锁的是当前实例对象this;
  • 静态方法锁的是当前类的Class对象(ClassName.class);
  • 多个对象之间共享一个资源(如:数据库连接池)用静态同步方法。

6. Synchronized和ReentrantLock的区别:

  • Synchronized可以修饰静态方法、普通方法和代码块,ReentrantLock只能修饰代码块;
  • Synchronized自动加锁释放锁,ReentrantLock需要手动加锁释放锁;
  • Synchronized是非公平锁,Synchronized和ReentrantLock既可以是公平锁也可以是非公平锁;
  • Synchronized不可响应中断,ReentrantLock可响应中断,解决死锁问题;
  • Synchronized是JVM层面通过监视器实现的,ReentrantLock是基于AQS实现的;

7. 怎么理解可重入锁:

  • 可重入锁指同一个线程在获取了锁之后,可以重复获取该锁,而不会造成死锁(阻塞导致)或其他问题。
  • ReentrantLock实现可重入锁机制是基于线程持有锁的计数器,每重复获取一次就+1,释放-1,减到0才会完全释放。
  • Synchronized是可重入的,当一个线程调用Synchronized方法的同时在其方法内部调用该对象另一个Synchronized方法,即一个线程得到对象锁之后再次请求该对象锁是允许的,底层是操作系统的互斥锁(mutex lock),每个可重入锁会关联一个线程ID和一个锁状态status(也类似于一个计数器)。

8. Synchronized锁升级过程:

复制代码
无锁->偏向锁->轻量级锁->重量级锁
bash 复制代码
   ┌─────────────┐
   │   无锁       │
   └─────┬───────┘
         ↓ (加锁,第一次使用)
   ┌─────────────┐
   │ 偏向锁       │ ←------ 若只有一个线程反复使用,保持偏向锁
   └─────┬───────┘
         ↓(有其他线程竞争)
   ┌─────────────┐
   │ 轻量级锁     │ ←------ 若竞争不激烈,用CAS自旋
   └─────┬───────┘
         ↓(竞争激烈,CAS自旋失败)
   ┌─────────────┐
   │ 重量级锁     │
   └─────────────┘

9. JVM对Synchronized锁优化:

  • 锁膨胀:没有一开始就用重量级锁,避免获取和释放锁的时候用户态到内核态的转换;
  • 锁消除:JVM检测不到某段代码块被共享和竞争的可能性,就将这段的同步锁消掉;
  • 锁粗化:将多个连续的加锁、解锁操作连接在一起,扩展成范围更大的锁;
  • 自旋锁:避免挂起和恢复的开销,因为挂起和恢复操作都需要从用户态转入内核态;

10. 参考

https://www.xiaolincoding.com/interview/juc.html#并发安全

相关推荐
小徐Chao努力10 分钟前
【解析】ReentrantLock锁、Syschronized锁面试点解析
java·面试·职场和发展·synchronized·
V少年20 分钟前
深入浅出Java线程池
android·java
顾林海26 分钟前
深度解析Hashtable工作原理
android·java·面试
只恨天高29 分钟前
SpringBoot异常处理之注解@ExceptionHander和@ControllerAdvice
java·spring boot·spring
都叫我大帅哥33 分钟前
Java中的Collection必知必会
java
都叫我大帅哥36 分钟前
代码界的「跨界婚姻」:桥接模式的鹊桥艺术
java·后端·设计模式
汤姆yu1 小时前
Spring 中的 @Cacheable 缓存注解
java·spring·缓存
老码识土1 小时前
kotlin 协程源代码泛读:引子
java
小智疯狂敲代码1 小时前
Spring AOP源码-JDK 与 CGLIB 动态代理的抉择与实现
java·面试
一介输生1 小时前
Spring Boot 实现权限管理(下)
java·后端