迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Java >

Java 中的 volatile 关键字

作者:迹忆客 最近更新:2023/11/13 浏览次数:

Java 是一种非常流行的编程语言,通过了解 Java,我们可以很容易地理解它为什么会在编程社区中获得这样的地位。

Java 为我们提供了大量有用的资源,我们可以在程序中使用这些资源来编写所需的逻辑。

Java 对于多用途编程问题很有用,其中一个这样的编程问题是使用线程或不同逻辑程序的并行执行。

本文将探索和理解 Java 中的 volatile 关键字、它的属性以及它在实际编程中的用法。我们将了解何时使用 volatile 关键字、其重要性以及何时以及不应使用。

本文还将提供一个基本的示例代码来帮助你理解 volatile 关键字。


Java 中的 volatile 关键字

在使用 Java 时,你可能遇到过并行线程和 synchronized 关键字。volatile 关键字与 synchronized 关键字相似,但又完全不同。

volatile 关键字在我们的代码中很容易理解和实现,并且比 synchronized 锁定机制具有更少的运行时开销。然而,volatile 关键字不如 synchronized 锁定强大。

volatile 关键字确保对共享 volatile 变量所做的更改立即反映在所有线程中。synchronized 关键字用于实现 Java 中的锁机制,锁提供可见性和原子性。

但是,volatile 关键字只能实现可见性,不能实现原子性。因此,我们可以理解,volatile 关键字只能在极少数情况下使用。

例如,当变量的值独立于所有其他变量和案例,甚至独立于自身时,我们可以使用它。


在 Java 中我们什么时候使用 volatile 关键字

正如我们已经看到的,在 volatile 关键字的帮助下,共享变量的更改值会立即反映在所有其他线程中。因此,我们在处理线程中的共享变量时使用它。

synchronized 关键字已经可用时,你可能会问为什么我们使用 volatile 关键字?但是,volatile 关键字更易于理解且性能更好。

因此,在某些情况下,我们可能想要使用它。例如,当我们有大量的读取操作和少量的写入操作时,我们希望使用 volatile 关键字以获得更好的性能。

此外,volatile 关键字提供了更好的可伸缩性,因为它不会导致线程阻塞。

为了更好地理解我们可以安全有效地使用 volatile 关键字的情况,我们应该注意以下情况。

  • 程序的当前和其他变量和状态之间不应存在相互依赖关系。
  • 变量不应依赖于自身。

因此,如果我们的变量完全独立于自身,我们可以使用代码的 volatile 关键字。

但是,我们经常遇到不满足第一个或第二个条件或两个条件的情况。因此,volatile 关键字的使用受到很大限制。

请注意许多程序员犯的一个非常微妙的错误。很多时候,程序员倾向于将增量运算符视为单个操作。

但是,增量运算符(或减量运算符)由多个操作组成,并且发生在多个阶段。因此,在这种情况下,我们不应该使用 volatile 关键字。


Java 中 volatile 关键字的性能优势

虽然 volatile 关键字简单易用,但它的性能优于锁定机制。在某些情况下,可以看出 volatile 的性能比 synchronized 好得多。

然而,事情并没有那么简单。当我们有 Java 虚拟机(JVM)时,很难正确判断这两个关键字的性能。

是因为 JVM 进行了优化,有时候加锁是不需要的,JVM 在代码优化的时候把它去掉了。但是,通常观察到易失性读取在性能方面非常好,并且可以与普通读取相媲美。

然而,易失性写入比普通写入要昂贵得多。另一方面,易失性写入总是比获取锁便宜。

因此,我们应该考虑 volatile 关键字和 synchronized 锁定机制之间的性能比较。

我们已经讨论了 volatile 的另一个性能优势:它不会导致线程阻塞并且在可扩展性方面要好得多。这是使用 volatile 关键字的另一个原因。


在 Java 中使用 volatile 关键字

我们将在下面的代码中了解如何在我们的 Java 代码中使用 volatile 关键字。

sharedObj.java

public class sharedObj {
  volatile boolean flag;
}

ThClass.java

public class ThClass extends Thread {
  public sharedObj obj;
  public ThClass(sharedObj obj) {
    this.obj = obj;
  }

  @Override
  public void run() {
    super.run();
    while (true) {
      if (this.obj.flag)
        this.obj.flag = false;
      else
        this.obj.flag = true;
      System.out.println(obj.flag);
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

主类.java

import java.util.*;
public class MainClass {
  public static void main(String[] args) {
    sharedObj obj = new sharedObj();
    ThClass th1, th2;
    th1 = new ThClass(obj);
    th2 = new ThClass(obj);
    th1.run();
    th2.run();
  }
}

在上面给出的 Java 程序中,我们创建了三个不同的类。这些类解释如下。

  • sharedObj.java:我们已经声明了一个在这个类中的线程之间共享的可变共享变量。
  • ThClass.java:这个类用于创建线程。它扩展了 Thread 类并覆盖了 run() 方法。每个线程休眠 1 秒。
  • MainClass.javaMain 类是实现 main() 方法的最重要的类,从执行开始。我们创建了两个线程,并通过构造函数传递了一个共享对象作为参数。

该 Java 程序的输出如下所示。

true
false
true
false
true
false

请注意,此代码运行无限时间,要停止它,你必须手动停止它的执行。 (例如,在 Linux 上按 CTRL+C)。


结论

在本文中,我们了解了 volatile 关键字、它的优缺点以及何时可以使用它。虽然 volatile 关键字不如同步锁定机制强大,但它仍然在实践中使用。

我们仍然使用 volatile 关键字,因为它在代码中更容易理解和实现,比锁具有更好的性能,并且更容易扩展,因为它不锁定线程。

但是,在代码中使用 volatile 关键字时,应始终小心检查条件,以免发生意外错误。

本文提到了检查 volatile 关键字是否适用的简单步骤;检查使用这些步骤以了解 volatile 是否适用于你的代码。

这将有助于在同步锁定机制和 volatile 关键字之间进行选择。

上一篇:修复 Java NoClassDefFoundError 错误

下一篇:没有了

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

修复 Java NoClassDefFoundError 错误

发布时间:2023/11/13 浏览次数:199 分类:Java

本文介绍如何修复 Java 中的 NoClassDefFoundError。在 Java 语言中,错误是主要由于缺乏资源而发生的异常。此外,错误无法在编译时捕获并在运行时发生。

在 Java 中扩展 Comparable

发布时间:2023/10/19 浏览次数:97 分类:Java

本教程展示了如何在 Java 中清除 StringBuilder 本指南将了解在 Java 中扩展 Comparable 接口。它写成 Comparable。它是一个由 Java 中的许多类实现的接口。

Java 中的 Predicate 是什么

发布时间:2023/10/19 浏览次数:109 分类:Java

本文介绍 Java 8 中的 Predicate 接口。本教程通过 Java 示例介绍 Predicate 接口。Predicate 是 Java 中的一个接口,用作 lambda 表达式或方法引用的目标赋值。

Java 输出参数

发布时间:2023/10/19 浏览次数:93 分类:Java

本教程演示了 Java 是否有类似 C# 的 out 参数关键字。Java 不支持像 C# 中的 out 和 ref 之类的关键字在方法中通过引用传递,因为值仅在 Java 中传递参数。该值甚至通过引用。

Java 中的 parameter 与 argument

发布时间:2023/10/19 浏览次数:84 分类:Java

本文介绍 Java 中 parameter 和 argument 的区别。本教程通过 Java 中的示例介绍 parameter 和 argument 之间的区别。

在 Java 中画一个圆

发布时间:2023/10/19 浏览次数:189 分类:Java

本教程介绍如何在 Java 中使用几个函数画圆在本文中,我们将介绍如何使用用于创建 GUI 组件的库 java.awt 和 javax.swing 在 Java 中绘制一个圆。

在 Java 中画一个三角形

发布时间:2023/10/19 浏览次数:143 分类:Java

本教程介绍了如何在 Java 中画一个三角形。在本文中,我们将学习如何在 Java 中绘制一个三角形。我们使用 AWT(Abstract Window Component Toolkit),这是最早的 Java 开发包,

用 Java 画一条线

发布时间:2023/10/19 浏览次数:92 分类:Java

本文介绍了如何使用 Applet 在 java 中绘制线条。Java 中的 Java.awt.Graphics 类构成了许多此类绘图和图形功能的基础。

Java 中的消息框

发布时间:2023/10/19 浏览次数:155 分类:Java

本文介绍如何在 Java 中显示消息框。Java 中的消息框是​​出现在屏幕上的弹出窗口,用于显示一些消息并等待用户确认。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便