1865 字
约 6 分钟
9
Java JUC教程

Java JUC教程第1章:并发编程基础

章节头部 第1章

⚡ 并发编程基础

理解并发编程的基本概念、Java内存模型和线程安全问题的根源
学习目标

学习目标

  • 理解并发编程的基本概念和重要性
  • 掌握并发与并行的区别
  • 了解Java内存模型(JMM)
  • 认识线程安全问题的根源
  • 理解可见性、原子性、有序性三大特性

什么是并发编程

什么是并发编程

并发编程(Concurrent Programming)是指在同一时间段内执行多个任务的编程方式。在现代计算机系统中,并发编程已经成为提高程序性能和响应能力的重要手段。

核心理解

并发编程不仅仅是技术层面的多线程,更是一种解决复杂问题的思维方式,它能够充分利用现代多核处理器的计算能力。

并发编程的应用场景

Web服务器同时处理多个用户请求,提高服务器的吞吐量和响应速度。桌面应用UI线程与后台任务分离,保证用户界面的流畅性。数据处理并行处理大量数据,提高数据分析和计算的效率。

并发编程的优势

  • 提高性能:充分利用多核CPU的计算能力
  • 改善响应性:避免程序因长时间操作而卡顿
  • 增强吞吐量:同时处理更多的任务和请求
  • 资源利用率:更好地利用系统资源

并发 vs 并行

并发 vs 并行

并发(Concurrency)和并行(Parallelism)是两个容易混淆的概念,理解它们的区别对于掌握并发编程至关重要。
并发(Concurrency)
同一时间段内处理多个任务,但不一定同时执行。通过时间片轮转等方式在单核CPU上实现。

  • 逻辑上的同时进行
  • 可以在单核CPU上实现
  • 关注任务的组织和调度

并行(Parallelism)
同一时刻真正同时执行多个任务,需要多核CPU或多台机器的支持。

  • 物理上的同时进行
  • 需要多核CPU支持
  • 关注任务的同时执行

重要区别

并发是关于处理多个任务的能力,而并行是关于同时执行多个任务的能力。并发可以在单核上实现,但并行必须要有多核支持。
Java内存模型

Java内存模型(JMM)

Java内存模型(Java Memory Model,JMM)定义了Java程序中各种变量的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这样的底层细节。

内存模型结构

主内存(Main Memory)
所有线程共享的内存区域,存储所有变量的主副本。

  • 存储实例字段、静态字段
  • 所有线程都能访问
  • 变量的唯一主副本

工作内存(Working Memory)
每个线程私有的内存区域,存储主内存中变量的副本。

  • 线程私有,相互隔离
  • 存储变量的副本
  • 直接操作工作内存

内存交互操作

JMM定义了8种内存交互操作,用于控制主内存与工作内存之间的数据传输:

  • lock(锁定):作用于主内存变量,标识变量为线程独占
  • unlock(解锁):作用于主内存变量,释放锁定状态
  • read(读取):从主内存读取变量值到工作内存
  • load(载入):将read的值放入工作内存的变量副本
  • use(使用):将工作内存变量值传递给执行引擎
  • assign(赋值):将执行引擎的值赋给工作内存变量
  • store(存储):将工作内存变量值传送到主内存
  • write(写入):将store的值写入主内存变量

线程安全问题

线程安全问题

当多个线程同时访问共享资源时,如果没有适当的同步机制,就可能出现线程安全问题。这些问题的根源在于并发访问共享数据时的竞态条件。

经典案例:不安全的计数器

UnsafeCounter.java

public class UnsafeCounter {
    private int count = 0;
    
    public void increment() {
        count++; // 这不是原子操作!
    }
    
    public int getCount() {
        return count;
    }
    
    public static void main(String[] args) throws InterruptedException {
        UnsafeCounter counter = new UnsafeCounter();
        
        // 创建1000个线程,每个线程执行1000次increment
        Thread[] threads = new Thread[1000];
        for (int i = 0; i < 1000; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    counter.increment();
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        
        // 期望结果:1000000,实际结果:可能小于1000000
        System.out.println("最终计数: " + counter.getCount());
    }
}

问题分析

count++操作实际包含三个步骤:读取count值、将值加1、写回count。在多线程环境下,这三个步骤可能被其他线程打断,导致数据不一致。

常见的线程安全问题

竞态条件多个线程同时访问和修改共享数据,最终结果依赖于线程执行的时序。数据竞争多个线程同时访问同一内存位置,且至少有一个是写操作,没有适当的同步。死锁两个或多个线程相互等待对方释放资源,导致程序永久阻塞。 可见性、原子性、有序性

可见性、原子性、有序性

并发编程中的三大特性是理解线程安全问题的关键。Java内存模型正是围绕这三个特性来设计的。
可见性(Visibility)
当一个线程修改了共享变量的值,其他线程能够立即看到这个修改。
可见性问题示例

public class VisibilityDemo {
    private boolean flag = false;
    
    public void writer() {
        flag = true; // 线程1修改
    }
    
    public void reader() {
        while (!flag) {
            // 线程2可能永远看不到flag的修改
        }
        System.out.println("Flag is true!");
    }
}

原子性(Atomicity)
一个操作或多个操作要么全部执行完成,要么全部不执行,不会被其他线程打断。
原子性问题示例

public class AtomicityDemo {
    private int count = 0;
    
    public void increment() {
        // 非原子操作:读取 -> 修改 -> 写入
        count = count + 1;
    }
    
    // 使用AtomicInteger保证原子性
    private AtomicInteger atomicCount = new AtomicInteger(0);
    
    public void atomicIncrement() {
        atomicCount.incrementAndGet(); // 原子操作
    }
}

有序性(Ordering)
程序执行的顺序按照代码的先后顺序执行,但编译器和处理器可能会进行指令重排序优化。
有序性问题示例

public class OrderingDemo {
    private int a = 0;
    private boolean flag = false;
    
    public void writer() {
        a = 1;          // 操作1
        flag = true;    // 操作2
        // 可能被重排序为:flag = true; a = 1;
    }
    
    public void reader() {
        if (flag) {     // 操作3
            int i = a;  // 操作4,可能读到a=0
        }
    }
}

解决方案预览

Java提供了多种机制来保证这三个特性:synchronized关键字、volatile关键字、Lock接口、原子类等。我们将在后续章节详细学习这些解决方案。
章节导航 返回目录 下一章:线程基础

Java JUC教程
https://clxhxhhr.top/posts/2773/
作者
clxstart
发布于
2026-09-19
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。