必须要学会的JMM与volatile

下面我为你详细讲解必须要学会的JMM与volatile的完整攻略。

JMM介绍

JMM(Java Memory Model)即Java内存模型,用于规范Java程序中线程对共享变量的操作。JMM为Java程序中的线程提供可见性、有序性、原子性等保证,从而提高程序并发性能。

JMM提供的保证

  • 可见性: 一个线程修改了共享变量的值,这个值的变化对其他线程是可见的。
  • 有序性: Java程序中的所有操作都是有序的,JMM通过禁止某些重排序优化来保证有序性。
  • 原子性: 对于某些复合操作,JMM保证这些操作要么全部执行,要么全部不执行。

JMM存在的问题

由于JVM的实现,每个线程都有自己的本地内存,线程之间的共享变量存于主内存中,因此在并发编程中需要考虑多线程之间的内存可见性和顺序性问题。

虽然JMM提供了可见性、顺序性、原子性的保证,但是只能保证某种程度的有序性和可见性,并不能保证所有的交互都按照开发人员预想的方式运行。

volatile关键字介绍

volatile关键字是JMM提供的一种保证内存可见性的手段。定义一个变量为volatile,JVM会避免执行重排序和缓存优化,保证该变量的每次写入都立即同步到主内存中,并且每次读取都从主内存中读取。

需要注意的是,volatile保证的是变量的可见性,保证的是单变量的操作是原子的,但是并不保证多次操作是原子的,因此对于多次操作的复合操作仍需使用锁或Atomic类进行保证。

volatile的用法

在Java中,声明一个变量为volatile需要使用volatile关键字来修饰:

public static volatile int count = 0;

在此例中,修饰的是静态变量count。该声明会告诉JVM将count存储到全局内存中,每个线程都将去电明这个全局变量,而且在修改count时会先更新到全局内存中。

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

public class VolatileTest {
    public static volatile int value = 0;

    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                while (value == 0) {
                }
                System.out.println("Value has changed,value=" + value);
            }
        }.start();

        // main thread paused for 1s to make sure that the new thread already started
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        value = 1;
        System.out.println("Value is ready to change,value=" + value);
    }
}

在该示例中,启动了一个新线程,并在该线程内部对value进行了轮询,判断value是否被main线程修改,如果修改过则打印修改后的结果。在main线程中,修改了value的值为1,此时新线程会感知到value已经被修改并且会结束轮询并打印修改后的结果。

volatile与JMM的关系

JMM中提供了volatile关键字作为保证可见性的手段。volatile可以在一定程度上解决Java编程中的内存可见性问题。但是需要注意的是,volatile仅能保证单个变量的可见性,如果需要保证复合操作的原子性还需要使用synchronized或者Atomic类。

在Java并发编程中,虽然volatile不能保证一些复合操作的原子性,但是在一些特定的场景下使用volatile仍然是非常有用的,例如状态标志、单例模式等。

以上就是“必须要学会的JMM与volatile”的完整攻略了。

阅读剩余 41%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:必须要学会的JMM与volatile - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • Java类之间的关系图_动力节点Java学院整理

    Java类之间的关系图_动力节点Java学院整理 在Java编程中,我们经常需要对类之间的关系进行分析和描述。类之间的关系可以用关系图来表示。在本文中,我们将讲解如何绘制Java类之间的关系图。 步骤1: 了解UML类图 UML(Unified Modeling Language)是一种用于软件设计的标准图形化语言。其中,类图是UML中最基本和最常用的图之一…

    Java 2023年5月26日
    00
  • jQuery form插件的使用之处理server返回的JSON, XML,HTML数据

    使用jQuery form插件可以方便地实现Ajax提交表单数据,同时也可以处理server返回的JSON、XML、HTML数据。下面是处理server返回的Json、XML和HTML数据的详细攻略。 一、处理server返回的JSON数据 (1)通过Ajax提交表单后,在success回调函数中使用jQuery.form的json解析方法解析返回的JSON…

    Java 2023年6月15日
    00
  • springboot springmvc抛出全局异常的解决方法

    下面是详细讲解“springboot springmvc抛出全局异常的解决方法”的完整攻略。 1. 场景描述 在开发Spring Boot和Spring MVC项目时,我们经常需要处理程序运行时的异常,这些异常可能会在控制器、服务或Spring Bean中发生。当运行时发生异常时,Spring Boot框架会抛出默认的异常界面,可能包含敏感信息,这不是我们想…

    Java 2023年5月27日
    00
  • 详解Java程序读取properties配置文件的方法

    当我们需要在Java程序中读取一些配置信息时,通常可以使用Properties文件作为配置文件,这种方式比硬编码更加灵活、易于维护。 以下是读取Properties配置文件的方法: 准备Properties文件 首先需要准备一个Properties文件。文件扩展名通常为.properties,它是一个文本文件,可以使用任何文本编辑器来编辑。属性文件由键值对组…

    Java 2023年5月20日
    00
  • Java Socket实现单线程通信的方法示例

    下面我会针对“Java Socket实现单线程通信的方法示例”的攻略进行详细解答。 1. 什么是Java Socket Java Socket是一种用于网络编程的API,它提供了简单、高效的网络通信方式,允许程序通过网络连接来进行数据传输。 2. Java Socket实现单线程通信的方法 2.1 创建服务器 下面是一个简单的Java Socket服务器实现…

    Java 2023年5月26日
    00
  • Serv-U 8.0 服务器中文乱码问题的解决

    这里是 Serv-U 8.0 服务器中文乱码问题的解决攻略。 问题描述 在 Serv-U 8.0 服务器中,当有中文字符传输时,会出现乱码问题,影响文件传输的正常使用。 解决方案 方案一:修改 Serv-U 的默认编码格式 Serv-U 8.0 服务器默认采用 ISO-8859-1 编码格式,而中文字符需要使用 UTF-8 编码格式才能正确显示。因此,我们需…

    Java 2023年5月20日
    00
  • JAVA实现空间索引编码——GeoHash的示例

    想要详细讲解“JAVA实现空间索引编码——GeoHash的示例”的完整攻略,可以按照以下步骤进行: 1. 了解GeoHash GeoHash是一种基于经纬度坐标存储和索引的编码方式,将二维的经纬度坐标转换为字符串形式进行存储,以达到快速空间索引的目的。在GeoHash编码中,每个字符对应的是一段矩形区域,在进行空间查询的时候,只需要将查询范围转化为对应的Ge…

    Java 2023年5月20日
    00
  • JAVA线程sleep()和wait()详解及实例

    JAVA线程sleep()和wait()详解及实例 简介 Java中的线程是轻量级的,同时也是一种几乎可以同时执行多个任务的机制。线程具有并发执行的能力,可以实现复杂的并发操作。线程的任何操作都需要以某种方式调度,由操作系统或JVM负责分配资源,因此线程通常比进程更高效。本文将重点介绍Java线程中的sleep()和wait()方法。 sleep()方法 s…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部