详解Java并发编程之volatile关键字

详解Java并发编程之volatile关键字

什么是volatile关键字?

volatile 是 Java 中一个非常重要的关键字,用于修饰变量,可以保证多个线程操作同一个变量时的可见性。当一个变量被 volatile 修饰时,线程每次对这个变量进行操作后,都会强制刷新本地缓存,使其他线程可以立即获取到最新的值。

volatile关键字的作用

volatile 可以保证多线程之间的可见性,防止多个线程操作同一变量时发生脏读,重复读,和读写颠倒的情况。使用 volatile 可以使线程在被阻塞时不会因为缓存数据的一致性问题导致死循环。

需要注意的是,volatile 并不能保证原子性。在多线程并发访问时,仅仅使用 volatile 是无法解决线程安全问题的。

volatile 和线程安全的实例说明

public class MyVolatileDemo {
    volatile int num = 0;

    public void increase() {
        num++;
    }

    public static void main(String[] args) throws InterruptedException {
        MyVolatileDemo demo = new MyVolatileDemo();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    demo.increase();
                }
            }).start();
        }
        Thread.sleep(5000);
        System.out.println("num=" + demo.num); // 输出的 num 值不能保证一定是 5000,因为 volatile 仅能保证可见性,无法保证原子性,需要配合 synchronized 等线程安全工具一起使用。
    }
}

上面这个例子中,我们创建了 5 个线程,每个线程对 num 变量调用 increase() 方法 1000 次,我们期望 num 的最终值应该是 5000,但是因为 volatile 并不保证原子性,所以输出结果并没有达到预期。

那么问题来了,怎样才能保证线程安全呢?可以使用 synchronized,把 increase() 方法加锁。

public class MyVolatileDemo {
    int num = 0;

    public synchronized void increase() {
        num++;
    }

    public static void main(String[] args) throws InterruptedException {
        MyVolatileDemo demo = new MyVolatileDemo();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    demo.increase();
                }
            }).start();
        }
        Thread.sleep(5000);
        System.out.println("num=" + demo.num); // 此时输出的 num 值始终为 5000,解决了线程安全问题。
    }
}

总结

使用 volatile 变量可以保证线程之间的可见性,但是不能保证原子性。想要保证线程安全,需要使用到 synchronized 或者其他的线程安全工具,以保证多线程操作的原子性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Java并发编程之volatile关键字 - Python技术站

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

相关文章

  • jdk自带线程池实例详解

    JDK自带线程池实例详解 线程池介绍 在应用程序开发中,使用线程是很常见的。当一个程序被执行时,它会生成一个主线程,这个主线程可以并行运行多个程序段。但如果程序中包含多个任务需要同时运行时,如果每个任务都创建自己的线程,这将会导致线程的大量创建和销毁,极度浪费资源。而线程池的出现解决了这个问题,它将多个任务合并在一起,让它们共享一个线程池中的线程完成任务。 …

    多线程 2023年5月16日
    00
  • Java经典面试题汇总–多线程

    Java经典面试题汇总–多线程 前言 在Java开发中涉及到多线程的知识点比较多,同时也是面试中经常涉及到的内容。因此,掌握Java多线程相关的知识是非常有必要的。 多线程基础 1. 多线程的定义 多线程指的是在一个程序中执行多个线程,执行的过程中它可以同时运行多个任务,可以使用多个CPU。多线程可以提高程序的并发性,从而提高系统的资源利用率和效率。 2.…

    多线程 2023年5月17日
    00
  • Java多线程之并发编程的核心AQS详解

    Java多线程之并发编程的核心AQS详解 什么是AQS AQS,即AbstractQueuedSynchronizer,是Java多线程并发包(java.util.concurrent)中的一个核心组件,用于构建锁和其他同步工具的基础框架。 AQS 中提供了一些基本的同步状态管理功能,包括获取和释放锁、管理同步状态、阻塞线程等。AQS 的一个重要特性是可以通…

    多线程 2023年5月16日
    00
  • golang并发锁使用详解

    Golang并发锁使用详解 什么是并发锁 在 Go 语言中,关于并发锁的讨论,并不仅限于第三方库,而是深入在编程语言的核心API 规范里的。Go语言提供了有助于编码并发应用的丰富API,而这些API中锁的使用无疑是其中重要组成部分。说起锁,就不得不提到 Race Condition(竞争条件) 了。在竞争条件的情况下,Go程序会发生不可预期和不稳定的行为,为…

    多线程 2023年5月17日
    00
  • Java多线程模式之Balking模式详解

    Java多线程模式之Balking模式详解 什么是Balking模式 Balking模式是一种简单的多线程模式,旨在防止多个线程同时执行相同的操作。在Balking模式中,如果发现已经存在一个等待被处理的请求,则不会再创建一个新的请求。 Balking模式的工作原理 如果线程想要执行某个任务,它会首先检查某个共享变量的状态。 如果共享变量的状态与线程所期望的…

    多线程 2023年5月17日
    00
  • 10张图总结出并发编程最佳学习路线

    首先我们需要了解什么是并发编程。并发编程是指同时执行多个线程或者进程来达到提高系统性能和处理能力的目的。但是并发编程存在着很多问题,例如资源竞争、死锁、协调通信等问题,因此在学习并发编程时需要掌握一些基本的知识和技能。 以下是“10张图总结出并发编程最佳学习路线”的完整攻略: 1. 并发模型 在学习并发编程之前需要了解并发模型的概念和各种模型的区别以及优劣,…

    多线程 2023年5月16日
    00
  • Java并发编程学习之ThreadLocal源码详析

    首先我们需要了解什么是ThreadLocal。ThreadLocal是一个与线程相关的类,它提供了线程本地存储(ThreadLocal Storage)功能,也就是说,对于同一个ThreadLocal实例,每个线程都可以获取相同但是独立的值。这样,多个线程之间可以相互独立,不会互相冲突,实现了数据的隔离。 一、ThreadLocal如何实现线程本地存储的在讲…

    多线程 2023年5月17日
    00
  • 详解Java实现多线程的三种方式

    详解Java实现多线程的三种方式 Java是一种支持多线程的语言,多线程可以带来更快的程序速度和更好的用户体验。Java实现多线程的方式有三种,分别是继承Thread类、实现Runnable接口和实现Callable接口。本文将详细介绍这三种方式的实现方法和示例代码。 继承Thread类 继承Thread类是Java实现多线程的一种方式。我们需要创建一个继承…

    多线程 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部