16、案例:volatile修饰变量并不能保证原子性

本文通过一个多线程示例展示了volatile关键字无法确保整型变量在并发环境下的原子性。介绍了原子性的概念,并通过实例代码解释了即使使用volatile修饰符,整型变量在多线程环境下进行累加操作仍可能出错。

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

一、什么是原子性

原子性,是指一批操作是一个整体,要么同时成功,要么同时失败,不能被干扰。

二、volatile修饰变量并不能保证原子性代码案例。

package com.zjl.study.多线程.volatile不能保证原子性案例;

/**
 * Created by zjl 2022/5/29
 **/
public class VolatileAtomic {

  public static void main(String[] args) {
    // 1、创建1个线程任务
    MyRunnable myRunnable = new MyRunnable();
    // 2、创建100个线程,执行100次任务,线程安全情况下,
    // 最终count值应该为 10000,但结果并不是
    for (int i = 1; i <= 100; i++) {
      new Thread(myRunnable).start();
    }
  }
}


class MyRunnable implements Runnable {

  private volatile int count;

  @Override
  public void run() {
    for (int i = 1; i <= 100; i++) {
      count++;
      System.out.println("count值为 ==============>  " + count);
    }
  }
}

三、运行结果

在这里插入图片描述

四、结论

创建100个线程,执行100次任务,每个任务累加100,如果volatile能保证原子性,最终count值应该为 10000,但结果并不是。说明,volatile修饰变量并不能保证原子性。

Java发编程中,Synchronized和Volatile关键字扮演着至关重要的角色,它们通过不同的机制来解决多线程环境下的原子性、可见性和有序性问题。首先,我们来看Synchronized关键字。它是一种同步锁机制,可以用来控制方法或者代码块在多线程中的执行顺序。Synchronized通过对象头中的Mark Word来实现锁机制,当一个线程获取到锁之后,其他的线程必须等待,直到锁被释放。这种机制保证了同时只有一个线程能够执行Synchronized修饰的方法或代码块,从而保证了操作的原子性。除此之外,Synchronized还能够确保锁对象的内存可见性,即当一个线程修改了对象状态后,其他线程访问该对象时将看到最新的状态,保证了可见性。同时,由于Synchronized会禁止指令重排序,因此也保证了有序性。Synchronized的升级优化机制,如偏向锁、轻量级锁、重量级锁,进一步提高了性能。 参考资源链接:[Java发编程:多线程与JMM深度解析](https://wenku.csdn.net/doc/6mxubscrmk?spm=1055.2569.3001.10343) 接下来是Volatile关键字Volatile关键字的引入主要是为了解决可见性问题。在多核处理器架构中,每个处理器都有自己的缓存,这会导致处理器缓存中的数据与主内存中的数据不一致。当一个变量被声明为Volatile时,JVM和编译器将确保该变量不会被缓存在寄存器或者缓存行中,每次使用变量时都会直接从主内存中读取,这就保证了不同线程对这个变量访问的可见性。此外,Volatile变量的读写都具有原子性,但这仅限于直接赋值操作,复合操作如i++保证原子性。在有序性方面,Volatile通过内存屏障来禁止指令重排序,确保指令按照代码的先后顺序执行。 在实际应用中,Synchronized和Volatile可以结合使用来解决更复杂的发问题。例如,当一个变量的更新需要保证原子性且需要在多线程之间保持可见性时,可以使用Synchronized来保证原子性操作,同时用Volatile保证变量的可见性。此外,对于那些不需要互斥访问的操作,可以单独使用Volatile保证有序性。 总的来说,理解和正确使用Synchronized和Volatile关键字对于编写线程安全的Java发程序至关重要。为了深入掌握这些概念,建议仔细阅读《Java发编程:多线程与JMM深度解析》这本书,它提供了关于Java内存模型、线程安全以及这些关键字使用的详细解释和案例分析,帮助开发者更全面地理解发编程的复杂性及其解决方案。 参考资源链接:[Java发编程:多线程与JMM深度解析](https://wenku.csdn.net/doc/6mxubscrmk?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值