java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java多线原子性、可见性、有序性

Java多线程三大特性之原子性、可见性、有序性详解

作者:奋进的芋圆

在并发编程中有三个非常重要的特性,分别是原子性、有序性,、可见性,这篇文章主要介绍了Java多线程三大特性之原子性、可见性、有序性的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

——含完整代码示例与底层原理剖析

文档目标:系统掌握 Java 并发三大核心特性的实现机制、使用场景及底层原理

一、引言:为什么需要三大特性?

在多线程环境中,多个线程共享内存,若不加控制,会出现以下问题:

Java 内存模型(JMM)通过 原子性(Atomicity)、可见性(Visibility)、有序性(Ordering) 三大特性保障并发安全。

⚠️ 注意:“一致性”不是 Java 并发三大特性的标准术语,常见于数据库(ACID)或分布式系统(CAP)。

二、三大特性定义

特性定义核心问题
原子性操作不可分割,要么全部执行成功,要么完全不执行复合操作被线程交错打断
可见性一个线程修改共享变量后,其他线程能立即看到最新值工作内存与主内存不同步
有序性程序执行顺序应符合代码编写顺序编译器/CPU 指令重排序

三、原子性(Atomicity)

1.synchronized—— JVM 内置锁

代码示例

public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++; // 非原子操作,需同步保护
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedExample e = new SynchronizedExample();
        Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) e.increment(); });
        Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) e.increment(); });
        t1.start(); t2.start();
        t1.join(); t2.join();
        System.out.println("Final count: " + e.count); // 输出 2000
    }
}

底层原理

2.ReentrantLock—— 显式可重入锁

代码示例

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private int count = 0;
    private final ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock(); // 必须在 finally 中释放
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentrantLockExample e = new ReentrantLockExample();
        Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) e.increment(); });
        Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) e.increment(); });
        t1.start(); t2.start();
        t1.join(); t2.join();
        System.out.println("Final count: " + e.count); // 输出 2000
    }
}

底层原理

3. 原子类(如AtomicInteger)

代码示例

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicExample {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet(); // 原子自增
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicExample e = new AtomicExample();
        Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) e.increment(); });
        Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) e.increment(); });
        t1.start(); t2.start();
        t1.join(); t2.join();
        System.out.println("Final count: " + e.count.get()); // 输出 2000
    }
}

底层原理

4.StampedLock—— 乐观读写锁

代码示例

import java.util.concurrent.locks.StampedLock;

public class StampedLockExample {
    private double x = 0, y = 0;
    private final StampedLock sl = new StampedLock();

    void move(double dx, double dy) {
        long stamp = sl.writeLock();
        try {
            x += dx;
            y += dy;
        } finally {
            sl.unlockWrite(stamp);
        }
    }

    double distanceFromOrigin() {
        long stamp = sl.tryOptimisticRead(); // 乐观读
        double currentX = x, currentY = y;
        if (!sl.validate(stamp)) { // 检查是否被写入
            stamp = sl.readLock(); // 升级为悲观读
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }

    public static void main(String[] args) {
        StampedLockExample obj = new StampedLockExample();
        obj.move(3, 4);
        System.out.println("Distance: " + obj.distanceFromOrigin()); // 输出 5.0
    }
}

底层原理

四、可见性(Visibility)

1.volatile—— 轻量级可见性保障

代码示例

public class VolatileVisibilityExample {
    private volatile boolean running = true; // volatile 保证可见性

    public void stop() {
        running = false;
    }

    public void runTask() {
        while (running) {
            System.out.println("Working...");
            try { Thread.sleep(500); } catch (InterruptedException e) { break; }
        }
        System.out.println("Task stopped.");
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileVisibilityExample task = new VolatileVisibilityExample();
        Thread worker = new Thread(task::runTask);
        worker.start();
        Thread.sleep(2000);
        task.stop(); // 主线程停止任务
        worker.join();
    }
}

❗ 若去掉 volatileworker 线程可能永远看不到 running = false,导致死循环。

底层原理

2.synchronized保证可见性

代码示例(复用前文SynchronizedExample)

底层原理

3.final字段的可见性

代码示例

public class FinalFieldExample {
    private final int x;
    private final int y;

    public FinalFieldExample(int x, int y) {
        this.x = x;
        this.y = y; // 构造完成后对所有线程可见
    }

    public int sum() {
        return x + y; // 无需同步,安全
    }

    public static void main(String[] args) {
        FinalFieldExample obj = new FinalFieldExample(3, 4);
        new Thread(() -> {
            System.out.println("Sum in thread: " + obj.sum()); // 输出 7
        }).start();
    }
}

底层原理

五、有序性(Ordering)

1.volatile禁止重排序(DCL 单例)

代码示例

public class DoubleCheckedLockingSingleton {
    // 必须加 volatile!否则可能返回未完全初始化的对象
    private volatile static DoubleCheckedLockingSingleton instance;

    private DoubleCheckedLockingSingleton() {}

    public static DoubleCheckedLockingSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckedLockingSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedLockingSingleton(); // 关键:防止重排序
                }
            }
        }
        return instance;
    }

    public void doSomething() {
        System.out.println("Singleton working...");
    }

    public static void main(String[] args) {
        DoubleCheckedLockingSingleton s1 = getInstance();
        DoubleCheckedLockingSingleton s2 = getInstance();
        System.out.println(s1 == s2); // true
        s1.doSomething();
    }
}

底层原理

2.synchronized保证有序性

代码示例(复用前文)

底层原理

六、综合对比表

方案原子性可见性有序性底层机制适用场景
synchronizedMonitor(对象头 Mark Word)通用同步,复合操作
ReentrantLockAQS + CAS + CLH 队列需要高级控制(超时、公平等)
原子类✅(单变量)CAS + volatile + Unsafe单变量无锁并发
StampedLock改进 AQS + 乐观读读多写少高性能场景
volatile✅(部分)内存屏障 + 缓存一致性协议状态标志、DCL 单例
final✅(构造后)✅(构造阶段)JMM final 语义不可变对象

七、最佳实践建议

八、附录:关键概念速查

概念说明
JMM(Java Memory Model)定义线程与主内存交互规则
happens-beforeJMM 核心规则,保证操作可见性与有序性
CAS(Compare-And-Swap)CPU 原子指令,无锁并发基础
AQSJUC 锁框架基石,基于 CLH 队列
内存屏障禁止指令重排序的硬件/编译器指令

💡 口诀记忆原(原子性)可(可见性)有(有序性)——Java 并发三基石。

到此这篇关于Java多线程三大特性之原子性、可见性、有序性详解的文章就介绍到这了,更多相关Java多线原子性、可见性、有序性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文