专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java并发编程从入门到进阶 多场景实战

temp10 2025-07-19 22:32:07 java教程 5 ℃ 0 评论

获课:keyouit.xyz/6121/

一文搞懂 Java 线程安全:原子性、可见性、有序性的底层原理

Java 线程安全是并发编程的核心议题,理解其底层原理需要深入 Java 内存模型(JMM)。本文将结合 JMM 解析并发编程的三大特性(原子性、可见性、有序性)及其典型线程安全问题。

Java并发编程从入门到进阶 多场景实战

一、Java 内存模型(JMM)基础

JMM 定义了线程和主内存之间的抽象关系:

  • 主内存(Main Memory):所有线程共享的内存区域
  • 工作内存(Working Memory):每个线程私有的内存区域,存储主内存的副本

线程操作流程:

  1. 线程读取变量时,从主内存复制到工作内存
  2. 线程修改变量时,先在工作内存修改,再刷新回主内存

二、并发编程的三大特性

1. 原子性(Atomicity)

定义:操作不可分割,要么全部执行,要么全部不执行

JMM 体现

  • 基本数据类型(除 long/double 外)的读写是原子的
  • volatile 保证变量的原子性读写(仅限 32 位)
  • synchronized 块中的操作是原子的

典型问题:竞态条件(Race Condition)

java


// 非原子操作导致的竞态条件


public class Counter {


private int count = 0;




public void increment() {


count++; // 非原子操作(读-改-写)


}


}

解决方案

  • 使用 synchronized
  • 使用 AtomicInteger 等原子类

2. 可见性(Visibility)

定义:一个线程对共享变量的修改,能及时被其他线程看到

JMM 原因

  • 线程修改变量后,可能不会立即刷新到主内存
  • 其他线程可能读取到旧值(工作内存缓存)

典型问题

java


public class VisibilityProblem {


private static boolean flag = false;




public static void main(String[] args) {


new Thread(() -> {


while (!flag) { // 可能永远无法退出循环


// 业务逻辑


}


}).start();




try {


Thread.sleep(1000);


} catch (InterruptedException e) {


e.printStackTrace();


}




flag = true; // 修改可能不会立即被其他线程看到


}


}

解决方案

  • volatile 关键字
  • synchronized
  • final 关键字(初始化时保证可见性)

3. 有序性(Ordering)

定义:程序执行的顺序按照代码的先后顺序执行

JMM 原因

  • 编译器优化(指令重排)
  • 处理器优化(乱序执行)
  • 内存系统的重排序

典型问题

java


public class ReorderingProblem {


private static int x = 0, y = 0;


private static int a = 0, b = 0;




public static void main(String[] args) throws InterruptedException {


Thread one = new Thread(() -> {


a = 1;


x = b; // 可能读取到 b=0


});




Thread two = new Thread(() -> {


b = 1;


y = a; // 可能读取到 a=0


});




one.start();


two.start();


one.join();


two.join();




System.out.println("(" + x + "," + y + ")"); // 可能输出 (0,0)


}


}

解决方案

  • volatile 禁止指令重排
  • synchronized
  • happens-before 原则

三、happens-before 原则

JMM 定义了 8 条 happens-before 规则,用于保证程序的执行顺序:

  1. 程序顺序规则:一个线程中的每个操作,happens-before 于该线程中的任意后续操作
  2. 监视器锁规则:对一个锁的解锁,happens-before 于随后对这个锁的加锁
  3. volatile 变量规则:对一个 volatile 域的写,happens-before 于任意后续对这个 volatile 域的读
  4. 传递性:如果 A happens-before B,且 B happens-before C,那么 A happens-before C
  5. start() 规则:如果线程 A 执行操作 ThreadB.start(),那么 A 线程的 ThreadB.start() 操作 happens-before 于线程 B 中的任意操作
  6. join() 规则:如果线程 A 执行操作 ThreadB.join() 并成功返回,那么线程 B 中的任意操作 happens-before 于线程 A 从 ThreadB.join() 操作成功返回
  7. 线程中断规则:对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  8. 对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的 finalize() 方法的开始

四、典型线程安全问题解决方案

1. 使用synchronized

java


public class SynchronizedCounter {


private int count = 0;




public synchronized void increment() {


count++; // 保证原子性、可见性和有序性


}




public synchronized int getCount() {


return count; // 保证可见性


}


}

2. 使用volatile

java


public class VolatileFlag {


private volatile boolean flag = false;




public void setFlag(boolean flag) {


this.flag = flag; // 保证可见性


}




public boolean getFlag() {


return flag; // 保证可见性


}


}

3. 使用原子类

java


import java.util.concurrent.atomic.AtomicInteger;




public class AtomicCounter {


private AtomicInteger count = new AtomicInteger(0);




public void increment() {


count.incrementAndGet(); // 保证原子性和可见性


}




public int getCount() {


return count.get(); // 保证可见性


}


}

4. 使用Lock接口

java


import java.util.concurrent.locks.Lock;


import java.util.concurrent.locks.ReentrantLock;




public class LockCounter {


private int count = 0;


private final Lock lock = new ReentrantLock();




public void increment() {


lock.lock();


try {


count++; // 保证原子性、可见性和有序性


} finally {


lock.unlock();


}


}




public int getCount() {


lock.lock();


try {


return count; // 保证可见性


} finally {


lock.unlock();


}


}


}

五、总结

  1. 原子性:操作不可分割,使用 synchronized、原子类等保证
  2. 可见性:一个线程的修改能被其他线程看到,使用 volatile、synchronized 等保证
  3. 有序性:程序执行顺序符合代码顺序,使用 volatile、synchronized 和 happens-before 原则保证

理解这些底层原理和解决方案,是编写高效、安全的并发程序的基础。在实际开发中,应根据场景选择合适的同步机制,平衡性能和安全性。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表