Java并发JUC(java.util.concurrent)Volatile单例模式CAS原子引用

本文详细介绍了Java并发编程中的关键概念,包括Volatile的可见性和禁止指令重排特性,单例模式的实现方式,以及CAS(Compare and Swap)操作的原理和Atomic引用在解决ABA问题上的应用。通过理解这些概念,开发者可以更好地掌握Java多线程编程的精髓。

在这里插入图片描述

???博主介绍:大家好,我是,一名在校大学生,热爱分享知识,很高兴在这里认识大家??
??擅长领域:Java、大数据、运维、电子
???如果本文章各位小伙伴们有帮助的话,??关注+???点赞+??评论+??收藏,相应的有空了我也会回访,互助!!!
??另本人水平有限,旨在创作简单易懂的文章,在文章描述时如有错,恳请各位大佬指正,在此感谢!!!


文章目录

Volatile
  • 保证可见性

    package icu.lookyousmileface.volatilecode;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @author starrysky
     * @title: VolatileUse
     * @projectName Juc_Pro
     * @description: volatile原子性测试
     * @date 2021/1/307:52 上午
     */
    public class VolatileShow {
        /**
         * // 不加 volatile 程序就会死循环!
         * // 加 volatile 可以保证可见性
         */
        private  volatile static int num = 0;
    
        public static void main(String[] args) {
    
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                    5,
                    Runtime.getRuntime().availableProcessors(),
                    5,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(3),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.DiscardOldestPolicy()
            );
            //线程1对内存中num=1的变化不知道
            threadPoolExecutor.execute(() -> {
                while (num == 0) {
    
                }
            });
    
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            num = 1;
    
            System.out.println("num:"+num);
    
            threadPoolExecutor.shutdown();
    
        }
    }
    
  • 不保证原子性

    原子性 : 不可分割

    线程A在执行任务的时候,不能被打扰的,也不能被分割。要么同时成功,要么同时失败。

    /**
     * @author starrysky
     * @title: VolatileNotAtomic
     * @projectName Juc_Pro
     * @description: Volatile不保证原子性
     * @date 2021/1/3011:32 上午
     */
    public class VolatileNotAtomic {
    
        private volatile static int num = 0;
    
        public  static void add(){
            num++;
        }
    
        public static void main(String[] args) {
    
            ThreadPoolExecutor threadPoolExecutor = new Thr
<think> 我们正在讨论`java.util.concurrent`包(简称JUC)的实现方式。这个包是Java并发编程的核心,提供了许多高级的并发工具。根据引用[1][3],JUC包含线程池、并发集合、同步器(如锁和信号量)、原子变量等。下面我将从几个关键部分详细说明其实现方式: ### 1. **线程池(Executor框架)** - **核心思想**:通过重用线程减少创建和销毁线程的开销。引用[3]提到,`ExecutorService`是线程池的核心接口,其实现如`ThreadPoolExecutor`使用工作队列(`BlockingQueue`)和线程工厂(`ThreadFactory`)。 - **工作流程**: 1. 提交任务(`execute()`或`submit()`)到线程池。 2. 若核心线程未满,则新建线程处理;否则任务入队。 3. 队列满时,若线程数未达最大值,新建非核心线程;否则触发拒绝策略(引用[4][5]的`RejectedExecutionException`即由此产生)。 - **关键代码结构**: ```java public class ThreadPoolExecutor extends AbstractExecutorService { private final BlockingQueue<Runnable> workQueue; // 任务队列 private final ReentrantLock mainLock = new ReentrantLock(); private final HashSet<Worker> workers = new HashSet<>(); // 工作线程集合 // 内部类Worker封装线程和任务 private final class Worker extends AbstractQueuedSynchronizer implements Runnable { final Thread thread; Runnable firstTask; // ... } } ``` ### 2. **并发集合(如ConcurrentHashMap)** - **实现方式**:采用分段锁(Java 7)或CAS+同步块(Java 8)。以`ConcurrentHashMap`为例: - **Java 7**:将数据分为多个段(`Segment`),每个段独立加锁,实现高并发读写。 - **Java 8**:使用`Node`数组+链表/红黑树,利用`sun.misc.Unsafe`类的CAS操作(如`compareAndSwapObject`)保证原子性,仅对桶的头节点加锁。 ### 3. **同步器(如AQS)** - **核心**:抽象队列同步器(`AbstractQueuedSynchronizer`, AQS)是锁(如`ReentrantLock`)和信号量(`Semaphore`)的基础[^1]。 - **原理**:通过FIFO队列管理等待线程,用`volatile int state`表示锁状态。关键方法: - `tryAcquire()`:尝试获取锁(子类实现)。 - `acquireQueued()`:将线程加入队列并阻塞(通过`LockSupport.park()`)。 ### 4. **原子变量(如AtomicInteger)** - **实现**:基于CAS(Compare-And-Swap)指令,直接调用硬件支持的原子操作。底层依赖`Unsafe`类: ```java public class AtomicInteger extends Number { private static final Unsafe unsafe = Unsafe.getUnsafe(); private volatile int value; public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; } } ``` ### 5. **Fork/Join框架** - **用途**:分治任务并行处理(如归并排序)。 - **实现**:`ForkJoinPool`使用工作窃取(Work-Stealing)算法:每个线程有自己的双端队列,空闲线程可从其他队列尾部“窃取”任务。 ### 总结 JUC的实现融合了以下技术: - **锁优化**:自旋锁、锁消除、锁粗化等(JVM层面)。 - **内存模型**:`volatile`和`final`保证可见性,`happens-before`规则排序指令。 - **底层API**:`Unsafe`类提供CAS和内存操作。 这些设计使JUC在高并发场景中高效且稳定,但需注意资源管理(如线程池关闭避免`RejectedExecutionException`[^4][^5])。 §§相关问题§§ 1. `ReentrantLock`和`synchronized`在JUC中的性能差异? 2. 如何正确配置线程池参数? 3. CAS操作在哪些场景下不适用? 4. `ConcurrentHashMap`在Java 8中如何解决哈希冲突? </think> `java.util.concurrent`(简称JUC)是Java并发编程的核心工具包,其实现基于多线程、内存模型、锁优化和原子操作等底层技术。以下是其关键实现机制的分析: --- ### 一、核心实现原理 #### 1. **锁机制(AQS框架)** - **抽象队列同步器(AQS)**:是`ReentrantLock`、`Semaphore`等同步器的基础[^1][^3]。 - 使用`volatile int state`表示锁状态(如锁计数、信号量许可数)。 - 通过FIFO双向队列(`Node`节点)管理等待线程。 - **关键操作**: - **获取锁**:`tryAcquire()`(子类实现具体逻辑)→ 失败则线程入队阻塞。 - **释放锁**:`tryRelease()` → 唤醒队列中的后继线程。 - **示例**:`ReentrantLock`通过继承AQS实现可重入锁。 #### 2. **线程池(Executor框架)** - **核心组件**[^3]: - **工作队列**:`BlockingQueue`(如`ArrayBlockingQueue`)存储待执行任务。 - **线程工厂**:`ThreadFactory`定制线程创建。 - **拒绝策略**:处理任务溢出(如触发`RejectedExecutionException`[^4][^5])。 - **工作流程**: ```mermaid graph LR A[提交任务] --> B{核心线程是否满?} B -->|未满| C[创建新线程执行] B -->|已满| D{队列是否满?} D -->|未满| E[任务入队] D -->|已满| F{线程数是否达上限?} F -->|未达| G[创建非核心线程] F -->|已达| H[触发拒绝策略] ``` #### 3. **原子操作(CAS指令)** - **Compare-And-Swap(CAS)**:通过`sun.misc.Unsafe`类调用CPU原子指令。 - 实现无锁并发(如`AtomicInteger`): ```java public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; } ``` - **优势**:避免线程阻塞,适用于高并发计数场景。 #### 4. **并发集合** - **分段锁技术**:`ConcurrentHashMap`将数据分段(Segment),每段独立加锁[^1]。 - **CAS优化**:Java 8+使用`synchronized+CAS`替代分段锁,提升并发度。 --- ### 二、底层技术依赖 1. **Java内存模型(JMM)** - 通过`volatile`(保障可见性)、`final`(禁止重排序)和`happens-before`规则保证线程安全。 2. **操作系统调度** - 线程阻塞/唤醒依赖操作系统调度器(如Linux的`futex`系统调用)。 3. **硬件支持** - CAS依赖CPU的原子指令(如x86的`CMPXCHG`)。 --- ### 三、典型问题与解决方案 1. **`RejectedExecutionException`** - **原因**:线程池已关闭或队列满[^4][^5]。 - **解决**:调整线程池参数或使用拒绝策略(如`CallerRunsPolicy`)。 2. **性能瓶颈** - **锁竞争**:用`ConcurrentHashMap`替代`synchronizedMap`。 - **线程开销**:使用线程池避免频繁创建/销毁线程[^3]。 --- ### 四、总结 `java.util.concurrent`的实现融合了: - **高层抽象**:AQS、Executor框架 - **底层优化**:CAS、内存屏障 - **资源管理**:线程池的动态扩缩容 这些设计使开发者能高效构建安全、高并发的应用[^1][^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值