Java内存模型与并发编程:如何高效、安全地写并发程序?

举报
喵手 发表于 2025/09/24 21:29:20 2025/09/24
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在我们今天的编程世界里,“并发”几乎无处不在:从网页的加载、APP的响应,到大规模分布式系统的运行。Java作为一种高效的编程语言,其强大的并发编程能力和内存模型为我们解决了很多并发问题。但与此同时,许多开发者可能在面对并发编程时感到一头雾水,如何确保线程之间的正确交互与同步?如何避免因线程共享数据而引发的各种问题?

今天,我们就来探讨一下 Java 内存模型(JMM)以及与并发编程相关的关键知识点,帮助你在并发编程的世界里畅游。我们将讲解 volatile 关键字、原子变量类、并发数据结构等,让你在高并发环境下高效、安全地处理多线程问题。


1. Java内存模型(JMM):多线程中的记忆与可见性

Java 内存模型(JMM,Java Memory Model)是 Java 中用于保证并发程序中多线程之间内存访问的规则。它定义了线程与内存之间的交互方式,确保了不同线程对共享数据的正确访问,特别是在多核处理器上,确保了线程之间的可见性原子性有序性

1.1 可见性问题

在 Java 中,每个线程都有自己的本地工作内存(线程栈),它缓存了主内存中的变量副本。当一个线程修改了共享变量时,另一个线程可能并不知道这个修改,从而导致数据不一致。JMM通过一些机制来确保线程之间共享数据的可见性。

1.2 原子性问题

原子性是指一个操作要么完全执行,要么完全不执行,不会被中断。在多线程环境中,如果多个线程同时修改某个变量,容易导致数据竞争,进而引发错误。JMM通过锁机制、synchronized关键字等来保证原子性。

1.3 有序性问题

有序性是指程序中的操作顺序。由于编译器优化和 CPU 指令重排,代码中的操作顺序可能和执行顺序不一致。在并发环境下,这种乱序执行可能导致意想不到的结果。JMM通过“ happens-before”规则来保证操作的执行顺序。


2. volatile关键字的作用与使用:轻量级的同步机制

为了保证多个线程之间对共享变量的可见性,Java 提供了 volatile 关键字。它的作用是:

  • 确保共享变量的修改对其他线程可见
  • 禁止指令重排,保证操作的有序性。

2.1 volatile的使用

public class VolatileExample {
    private static volatile boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        Thread writer = new Thread(() -> {
            try {
                Thread.sleep(1000);
                flag = true;
                System.out.println("Flag updated!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread reader = new Thread(() -> {
            while (!flag) {
                // 持续读取,直到flag的值改变
            }
            System.out.println("Flag is true, exiting reader thread.");
        });

        writer.start();
        reader.start();

        writer.join();
        reader.join();
    }
}

在这个例子中,volatile 关键字保证了线程 reader 能看到线程 writerflag 变量的修改。当 flag 设置为 true 时,reader 线程能立刻感知到并退出循环。

2.2 volatile的限制

尽管 volatile 可以解决可见性问题,但它无法保证原子性。例如,如果你有一个类似 count++ 的操作,volatile 无法保证多个线程对 count 的操作是安全的。这时候,我们就需要借助更强大的同步机制。


3. 原子变量类(AtomicInteger、AtomicReference等):保证原子性

如果你需要在并发环境中处理一些简单的数值操作,同时保证操作的原子性,Java 提供了 原子变量类(如 AtomicIntegerAtomicReference 等)。它们是通过底层的 CAS(Compare-And-Swap)机制来实现的,能够保证线程安全。

3.1 AtomicInteger的使用

AtomicInteger 提供了一些常用的方法,例如 incrementAndGet()decrementAndGet() 等,来对整数进行原子性操作。

import java.util.concurrent.atomic.AtomicInteger;

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

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                count.incrementAndGet();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Final count: " + count.get());
    }
}

在这个例子中,AtomicInteger 确保了 count 变量的操作是原子性的。无论多少线程同时修改 count,都不会发生数据竞争,最终输出的结果是准确的。

3.2 AtomicReference的使用

AtomicReference 类提供了对对象引用的原子性操作,适用于需要保证原子性的引用类型变量。

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceExample {
    public static void main(String[] args) {
        AtomicReference<String> atomicStr = new AtomicReference<>("Initial");

        atomicStr.set("Updated");
        System.out.println("AtomicReference Value: " + atomicStr.get());
    }
}

AtomicReference 使得在多线程环境中修改引用类型对象的操作变得安全,避免了因多个线程并发访问引用对象而产生的问题。


4. 并发数据结构:提升并发编程效率

Java 提供了一些并发数据结构,它们能够有效地解决多线程访问共享数据时产生的问题。这些数据结构在设计时已经考虑了线程安全问题,避免了手动加锁的麻烦。

4.1 ConcurrentHashMap:高效的线程安全哈希表

ConcurrentHashMap 是一个线程安全的哈希表,它允许多个线程并发读取数据,并且在更新操作时不会阻塞其他线程的读取。

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) throws InterruptedException {
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                map.put("key-" + i, "value-" + i);
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Map size: " + map.size());
    }
}

ConcurrentHashMap 允许多个线程并发地执行 putget 操作,而不必显式加锁,它在设计时通过将数据划分为多个段,每个段单独加锁,从而实现高效的并发操作。

4.2 CopyOnWriteArrayList:线程安全的列表

CopyOnWriteArrayList 是一个线程安全的列表实现,它通过在修改操作时复制整个数组,从而避免了并发修改时出现的异常。

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) throws InterruptedException {
        List<String> list = new CopyOnWriteArrayList<>();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                list.add("element-" + i);
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("List size: " + list.size());
    }
}

CopyOnWriteArrayList 的每次修改操作都会复制数组,这意味着它的写操作比较慢,但读操作非常快速,适用于读多写少的场景。


结语:高效的并发编程,让你驾驭多线程世界

通过对 Java 内存模型(JMM)以及并发编程相关内容的学习,你应该对如何高效、安全地编写并发程序有了更深的理解。从保证线程之间的可见性到处理原子操作,再到使用并发数据结构,Java 提供了丰富的工具来帮助我们轻松处理多线程问题。

记住,写好并发程序不仅仅是为了提高性能,更是为了确保程序在复杂的多线程环境中始终保持正确性。加油,开始写出高效、优雅的并发代码吧!

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。