Java并发编程 - JMM详解

Java内存模型(Java Memory Model,简称JMM)是Java虚拟机规范中定义的一套规则,用于描述Java程序中的内存一致性模型。JMM规定了程序中各种变量(线程共享变量)的访问规则,以及在并发环境下如何保证内存的可见性、有序性和原子性。理解JMM对于正确地编写并发程序至关重要。

Java内存模型的关键概念

1. 主内存与工作内存
  • 主内存(Main Memory):JMM的概念化内存区域,所有线程共享的内存区域,存储了所有线程可见的变量(实例字段、静态字段和数组元素)的最终值。
  • 工作内存(Working Memory):每个线程拥有的私有内存区域,用于存储该线程使用的变量的副本。
2. 内存操作
  • lock(锁定):作用于主内存变量,把一个变量标识为一条线程独占的状态。
  • unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read(读取):作用于主内存变量,把一个变量的值从主内存转移到线程的工作内存。
  • load(载入):作用于工作内存变量,把read操作从主内存得到的变量值放入工作内存的变量副本中。
  • use(使用):作用于工作内存变量,把工作内存中的一个变量值传送给执行引擎。
  • assign(赋值):作用于工作内存变量,把从执行引擎接收到的值赋给工作内存的变量。
  • store(存储):作用于工作内存变量,把工作内存中的一个变量的值传送到主内存中。
  • write(写入):作用于主内存变量,它将store操作从工作内存中得到的变量的值放入主内存的变量中。
3. 内存可见性

内存可见性是指当一个线程修改了共享变量的值,其他线程能够立即看到这个修改。JMM通过在变量修改后将新值刷新回主内存,在变量读取前从主内存刷新变量值,来实现可见性。

4. 原子性

原子性是指一个操作要么全部完成,要么全部不完成。在JMM中,基本数据类型的变量读取和写入是原子操作,而复合操作(如自增)需要通过synchronized等同步机制来保证原子性。

5. 有序性

有序性指的是程序执行的顺序按照代码的先后顺序执行。然而,为了提高性能,编译器和处理器常常会对指令进行重排序。JMM通过在关键代码处插入内存屏障来禁止特定类型的指令重排序,从而保证有序性。

Java内存模型的规则

JMM定义了一系列规则来保证线程之间的正确交互:

  1. 不允许读/写重排序:读取操作(read)和写入操作(write)之间不能重排序。
  2. 不允许写/写重排序:两个写入操作(write)之间不能重排序。
  3. 锁规则:如果一个锁被释放,那么另一个线程可以获取这个锁。锁规则保证了锁的获取和释放操作不会被重排序。
  4. volatile变量规则:对volatile变量的写入会使其随后的写入操作发生之前,对volatile变量的读取会使其前面的读取操作发生之后。
  5. happens-before规则:如果一个操作happens-before另一个操作,那么第一个操作的结果对第二个操作可见,并且第一个操作按顺序发生在第二个操作之前。

volatile关键字

volatile关键字是JMM提供的一种轻量级的同步机制,它可以保证变量的可见性和有序性,但不保证原子性。当一个变量被声明为volatile时,意味着每次对该变量的写入都会直接写入主内存,每次读取都是直接从主内存中读取。

synchronized关键字

synchronized关键字可以用来保证原子性、可见性和有序性。它通过在变量上加锁来防止多个线程同时访问临界区。synchronized关键字可以用在方法或代码块上。

示例代码

下面是一个使用volatile关键字的简单示例:

public class VolatileExample {

    private volatile boolean stop = false;

    public void doWork() {
        while (!stop) {
            // 执行一些任务
        }
    }

    public void stopWork() {
        stop = true;
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileExample example = new VolatileExample();
        Thread worker = new Thread(example::doWork);
        worker.start();
        Thread.sleep(1000); // 等待一段时间
        example.stopWork(); // 设置停止标志
        worker.join(); // 等待worker线程结束
    }
}

在这个示例中,stop变量被声明为volatile,这意味着任何对它的写操作都会立即反映到主内存中,并且其他线程读取该变量时会直接从主内存中读取最新的值。

总结

Java内存模型是Java并发编程的基础,理解其核心概念和规则对于编写正确的并发程序至关重要。通过掌握JMM,开发人员可以更好地利用Java提供的并发工具,如volatilesynchronized,以及更高级的并发工具,如Atomic类和Lock接口,来构建高效且可靠的多线程应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值