学习Java内存模型JMM心得

学习Java内存模型JMM心得

什么是Java内存模型

Java内存模型(Java Memory Model,JMM)是一种用于保证在多线程情况下共享变量的可见性和有序性的机制。

JMM的核心概念

Java内存模型中有三个核心概念:原子性、可见性和有序性。

原子性

原子性指的是在同一时间只有一个线程可以访问共享变量。Java中的基本数据类型,如int、long等,都是具有原子性的。但是,对于复合操作,如i++,实际上是由多个步骤组成的,因此需要通过synchronized或者java.util.concurrent.locks中的锁机制来保证原子性。

可见性

可见性指的是一个线程对共享变量的修改,能够被其他线程及时地看到。在Java中,可以使用volatile关键字来保证可见性。通过volatile关键字,对该变量进行读操作时会直接从内存中读取最新的值,对该变量进行写操作时会立即将修改的值刷回到内存中。

有序性

有序性指的是指令执行的顺序,Java中通过happens-before的规则来保证有序性。happens-before的规则规定了一些时间上的先后顺序,例如在一个线程中,先发生的指令会先执行;在一个锁里,先释放锁的线程的操作happens-before于后获取锁的线程中的操作。

JMM的示例说明

示例1:通过volatile关键字保证变量可见性

下面是一段代码,其中共享变量flag未使用volatile关键字修饰:

class MyThread implements Runnable {
    private boolean flag = false;

    public void run() {
        while (!flag) {
            //Do something
        }
        System.out.println("Thread stopped.");
    }

    public void stop() {
        this.flag = true;
    }
}

public class VolatileTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        Thread t = new Thread(myThread);
        t.start();
        Thread.sleep(1000);
        myThread.stop();
    }
}

在上面代码中,flag被一个线程修改后,另一个线程无法及时地感知到其变化。因此,程序无法正常停止。现在我们通过将flag变量使用volatile关键字修饰,使其变为可见的。

class MyThread implements Runnable {
    private volatile boolean flag = false;

    public void run() {
        while (!flag) {
            //Do something
        }
        System.out.println("Thread stopped.");
    }

    public void stop() {
        this.flag = true;
    }
}

public class VolatileTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        Thread t = new Thread(myThread);
        t.start();
        Thread.sleep(1000);
        myThread.stop();
    }
}

示例2:使用锁机制保证原子性

下面是一个简单的例子,使用volatile关键字不足以保证原子性。

class MyRunnable implements Runnable {
    private volatile int count = 0;

    public void run() {
        for (int i = 0; i < 100000; i++) {
            count++;
        }
        System.out.println("count: " + count);
    }
}

public class VolatileAtomicityTest {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable);
        Thread t2 = new Thread(myRunnable);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

在上面的代码中,我们使用volatile关键字保证了count变量的可见性,但是由于count++操作是一个复合操作,因此并不具备原子性。运行上面的代码,就会发现输出的count的值并不是预期的200000。现在我们可以使用锁机制来保证原子性。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class MyRunnable implements Runnable {
    private int count = 0;
    private Lock lock = new ReentrantLock();

    public void run() {
        for (int i = 0; i < 100000; i++) {
            lock.lock();
            try {
                count++;
            } finally {
                lock.unlock();
            }
        }
        System.out.println("count: " + count);
    }
}

public class LockAtomicityTest {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable);
        Thread t2 = new Thread(myRunnable);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

在上述代码中,我们使用了Lock机制来保证了count变量的原子性。运行上面的代码,输出的count的值为200000,证明了操作的原子性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:学习Java内存模型JMM心得 - Python技术站

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

相关文章

  • 详解如何在spring boot中使用spring security防止CSRF攻击

    当开发一个基于web的应用程序时,防止CSRF攻击是非常重要的步骤。Spring Security提供了很多的功能和配置选项,旨在帮助我们保护Web应用程序。以下是在Spring Boot中使用Spring Security防止CSRF攻击的完整攻略。 1.添加Spring Security依赖 我们需要在项目的pom.xml文件中添加spring-boot…

    Java 2023年5月20日
    00
  • spring boot项目使用@JsonFormat失效问题的解决

    问题描述: 在Spring Boot项目中,使用@JsonFormat注解时,时间格式化不起作用,导致返回的时间格式不符合要求。如何解决这一问题? 解决方案: 引入依赖 首先,在项目的pom.xml文件中,引入以下依赖: <dependency> <groupId>com.fasterxml.jackson.datatype</…

    Java 2023年5月26日
    00
  • 输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程

    下面是详细讲解“输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程”的完整攻略。 什么是jstack信息 jstack 是 JDK 自带的一款堆栈跟踪工具,用于查看 Java 进程中各个线程的运行状态以及占用资源情况。通过分析线程堆栈信息,可以快速定位代码中的性能问题,排查进程死锁等问题。 如何输出jstack信息 下面是输出 ja…

    Java 2023年5月26日
    00
  • java过滤器中Filter的ChainFilter过滤链

    Java过滤器(Filter)可以用于拦截Web应用程序中的请求和响应,FilterChain(Filter链)则是一组过滤器,处理请求,并将请求和响应转发到下一个过滤器,最终传递给Servlet或JSP页面。 FilterChain的作用主要有两个: 1.按照指定的顺序传递请求和响应对象; 2.在所有的过滤器执行完毕之后,将请求和响应对象传递给Servle…

    Java 2023年6月15日
    00
  • Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.PathTranslator was bound

    这个错误提示通常是由于Intellij IDEA和Maven版本不匹配导致的。以下是一些解决此问题的攻略: 1. 通过设置maven home目录解决 请先确定你正在使用的Intellij IDEA是否与Maven版本兼容。在Intellij IDEA的Maven设置中,设置正确的Maven home目录。如果Maven home目录没有设置正确,会导致In…

    Java 2023年5月20日
    00
  • Java加密技术的作用是什么?

    Java加密技术的作用 Java加密技术的主要作用是保障数据的安全性,对敏感信息进行加密后再传输和存储,提高数据的安全性和可靠性。Java中提供了多种加密技术,包括对称加密和非对称加密,以及数字签名等技术,这些技术可以用来实现数据的加密、签名和认证等功能。 加密技术的分类 对称加密技术:使用同一个密钥进行加密和解密,加密和解密的速度比较快,但是安全性比较差。…

    Java 2023年5月11日
    00
  • 通过实例了解cookie机制特性及使用方法

    下面我将详细讲解“通过实例了解cookie机制特性及使用方法”的完整攻略。 什么是cookie cookie是一种客户端存储技术,用于保存用户在网站上的数据,常用的数据包括用户的登录状态、购物车内容等。cookie可以在不同的页面中共享数据,以此在用户与网站之间建立持久的关系。 cookie的特性 cookie是一种客户端存储技术,数据保存在用户的浏览器上;…

    Java 2023年5月20日
    00
  • iis、apache、nginx使用X-Frame-Options防止网页被Frame的解决方法

    在Web开发中,防止网页被Frame劫持成为了必须的安全措施之一,其中一个重要的方式是使用HTTP响应头中的“X-Frame-Options”来限制哪些网站可以使用Frame加载该网页。 不同的Web服务器软件可能实现方式略有不同,以下分别介绍如何在IIS、Apache以及Nginx中使用X-Frame-Options来防止网页被Frame。 IIS中使用X…

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