多线程系列(四) -volatile关键字使用详解

本文详细探讨了Java中的volatile关键字,包括其作用原理、保证内存可见性、禁止指令重排以及在单例模式中双重锁的使用场景。重点讲解了volatile如何解决多线程环境下的数据一致性问题,并对比了与synchronized的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

在上篇文章中,我们介绍到在多线程环境下,如果编程不当,可能会出现程序运行结果混乱的问题。

出现这个原因主要是,JMM 中主内存和线程工作内存的数据不一致,以及多个线程执行时无序,共同导致的结果。

同时也提到引入synchronized同步锁,可以保证线程同步,让多个线程依次排队执行被synchronized修饰的方法或者方法块,使程序的运行结果与预期一致。

不可否认,采用synchronized同步锁确实可以保证线程安全,但是它对服务性能的消耗也很大,synchronized是一个独占式的同步锁,比如当多个线程尝试获取锁时,其中一个线程获取到锁之后,未获取到锁的线程会不断的尝试获取锁,而不会发生中断,当冲突严重的时候,线程会直接进入阻塞状态,不能再干别的活。

为了实现线程之间更加方便的访问共享变量,Java 编程语言还提供了另一种同步机制:volatile域变量,在某些场景下使用它会更加方便。

一般来说,被volatile修饰的变量,可以保证所有线程看到这个变量都是同一个值,同时它不会引起线程上下文的切换和调度,相比synchronizedvolatile更加的轻量化。

比较官方的解释,volatile修饰变量有以下几个作用:

  • 1.保证变量的可见性,不保证原子性
    当用volatile修饰一个变量时,JMM 会把当前线程本地内存中的变量强制刷新到主内存中去,这个写操作也会导致其他线程中被volatile修饰的变量缓存无效,然后从主内存中获取最新的值

  • 2.禁止指令重排
    正常情况下,编译器和处理器为了优化程序执行性能会对指令序列进行重排序,当然是在不影响程序结果的前提下。volatile能够在一定程度上禁止 JVM 进行指令重排。

从概念上感觉比较难理解,下面我们结合几个例子,一起来看看它的具体应用。

二、volatile 使用详解

我们先看一个例子。

public class DataEntity {
   

    private boolean isRunning = true;

    public void addCount(){
   
        System.out.println("线程运行开始....");
        while (isRunning){
    }
        System.out.println("线程运行结束....");
    }

    public boolean isRunning() {
   
        return isRunning;
    }

    public void setRunning(boolean running) {
   
        isRunning = running;
    }
}
public class MyThread extends Thread {
   

    private DataEntity entity;

    public MyThread(DataEntity entity) {
   
        this.entity = entity;
    }

    @Override
    public void run() {
   
        entity.addCount();
    }
}
public class MyThreadTest {
   

    public static void <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值