Java 的并发编程模型:从 synchronized 到 CAS

举报
江南清风起 发表于 2025/03/21 20:15:57 2025/03/21
【摘要】 Java 的并发编程模型:从 synchronized 到 CAS在多核处理器和分布式系统日益普及的今天,并发编程变得越来越重要。Java作为一种广泛使用的编程语言,提供了丰富的并发编程模型和工具,使得开发者能够充分利用系统资源,提高程序性能。本文将深入探讨Java并发编程模型中两个重要的概念:synchronized和CAS(Compare-And-Swap),并结合代码实例进行详细讲解...

Java 的并发编程模型:从 synchronized 到 CAS

在多核处理器和分布式系统日益普及的今天,并发编程变得越来越重要。Java作为一种广泛使用的编程语言,提供了丰富的并发编程模型和工具,使得开发者能够充分利用系统资源,提高程序性能。本文将深入探讨Java并发编程模型中两个重要的概念:synchronized和CAS(Compare-And-Swap),并结合代码实例进行详细讲解。

一、Java并发编程基础

1.1 并发与并行

  • 并发:指多个任务在同一个时间段内同时开始但不一定同时结束。
  • 并行:指多个任务在同一时刻同时运行。

1.2 Java并发模型

  • 共享内存模型:Java线程共享同一个内存空间。
  • 消息传递模型:线程之间通过消息传递机制进行通信。

1.3 Java并发工具类

  • Thread:基本的线程类。
  • Runnable:线程接口。
  • Callable/Future:支持有返回值的任务。
  • ExecutorService:线程池接口。
  • ReentrantLock/Semaphore:锁和信号量。
  • AtomicVariables:原子变量类。
  • CountDownLatch/CyclicBarrier:同步辅助类。
  • BlockingQueue:阻塞队列。

二、synchronized关键字

2.1 synchronized原理

synchronized是Java中一个非常重要的关键字,用于保证多线程环境下的数据一致性和线程安全。它通过在对象头中设置一个monitor(监视器)来实现线程的同步。当一个线程进入synchronized代码块时,它会尝试获取对象的monitor。如果monitor已被其他线程占用,则当前线程会进入等待状态,直到monitor被释放。

2.2 synchronized的使用

2.2.1 同步方法

public class SynchronizedExample {
    public synchronized void synchronizedMethod() {
        // 同步方法代码
    }
}

2.2.2 同步代码块

public class SynchronizedExample {
    private Object lock = new Object();

    public void synchronizedBlock() {
        synchronized (lock) {
            // 同步代码块代码
        }
    }
}

2.3 synchronized的优势与局限性

  • 优势:简单易用,能够保证线程安全。
  • 局限性:性能较低,因为每次只有一个线程能够访问同步代码块或方法,其他线程需要等待。

三、CAS(Compare-And-Swap)

3.1 CAS原理

CAS是一种无锁的同步机制,它的核心思想是通过比较并交换来实现线程安全。CAS操作包含三个参数:内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值等于预期原值,则将该位置的值更新为新值,否则不进行任何操作。CAS操作是原子性的,即在单个机器指令中完成,不会被其他线程打断。

3.2 CAS在Java中的应用

Java中提供了AtomicIntegerAtomicLong等原子类来实现CAS操作。这些类提供了compareAndSet方法,用于执行CAS操作。

3.2.1 AtomicInteger的使用

import java.util.concurrent.atomic.AtomicInteger;

public class CASExample {
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public void increment() {
        atomicInteger.incrementAndGet();
    }

    public int getValue() {
        return atomicInteger.get();
    }

    public static void main(String[] args) {
        CASExample example = new CASExample();
        // 创建多个线程对atomicInteger进行递增操作
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    example.increment();
                }
            }).start();
        }
        // 等待所有线程执行完毕
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("最终结果:" + example.getValue());
    }
}

3.3 CAS的优势与局限性

  • 优势:性能较高,因为不需要线程的阻塞和唤醒。
  • 局限性:可能出现ABA问题,即在CAS操作期间,内存位置的值可能被其他线程修改后又恢复原值,导致CAS操作成功,但实际上数据已经被修改过。

四、synchronized与CAS的对比

4.1 性能对比

  • synchronized:在Java 6之后,JVM对synchronized进行了优化,包括锁粗化、锁消除、自旋锁等,使得synchronized的性能得到了显著提升。但在高并发场景下,仍然可能存在性能瓶颈。
  • CAS:由于不需要线程的阻塞和唤醒,CAS在高并发场景下通常具有更高的性能。

4.2 使用场景

  • synchronized:适用于需要保证线程安全且代码块较短的场景。
  • CAS:适用于高并发且需要频繁更新共享变量的场景。

五、总结

synchronized和CAS是Java并发编程模型中两种重要的机制。synchronized简单易用,能够保证线程安全,但在高并发场景下性能较低。CAS通过无锁的方式实现了高效的并发控制,但在某些情况下可能出现ABA问题。在实际开发中,我们需要根据具体的应用场景选择合适的并发控制机制,以提高程序的性能和可靠性。

image.png

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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