Java 中的原子性和内存顺序

Atomicity and memory order in Java

我是 Java 的新手,目前正在阅读 Java:初学者指南,第 6 版。我在 Java.

中遇到了一些关于原子性和内存顺序的混淆

书中涉及多线程的例子中,对共享资源(如共享变量)的并发访问是不同步的,共享资源也没有特别标记(如atomic或volatile等)。例如,在 Try This 15-1(第 519 页)中,对共享变量 stopFlag 的并发访问未序列化,也未特别标记该变量。

根据 this, certain data types in Java are guaranteed to be atomic even if they are not specifically marked. This somewhat solves the consideration concerning atomicity. But how about memory order? Does the default treatment imply sequential-consistency like the default memory_order_seq_cst 在 C++ 中访问原子类型的处理?

以下是示例中的一些关键代码片段。

public class Banner extends Applet implements Runnable {
  String msg = " Java Rules the Web ";
  Thread t;
  boolean stopFlag;
  // Initialize t to null.
  public void init() {
    t = null;
  }

  // Start thread
  public void start() {
    t = new Thread(this);
    stopFlag = false;
    t.start();
  }

  // Entry point for the thread that runs the banner.
  public void run() {
    // Redisplay banner
    for( ; ; ) {
      try {
        repaint();
        Thread.sleep(250);
        if(stopFlag) break;
      } catch(InterruptedException exc) {}
    }
  }

  // Pause the banner.
  public void stop() {
    stopFlag = true;
    t = null;
  }

  // Display the banner.
  public void paint(Graphics g) {
    char ch;
    ch = msg.charAt(0);
    msg = msg.substring(1, msg.length());
    msg += ch;
    g.drawString(msg, 50, 30);
  }

正如您链接的答案所解释的那样,原子性和可见性是完全不同的概念。 int 的原子性确保如果一个线程将 int 值从 5 更改为 -7,则其他线程可能会观察到 5 或 -7,但不会观察到其他任何东西。

可见性处理其他线程保证看到变量从 5 变为 -7 时。

你书中的例子可能是为了说明,除非 stopFlag 变量被声明为 volatile,它从一个线程的修改可能会立即对其他线程可见,或者在某个不确定的时间之后甚至从来没有。

没有

如果您使用像 AtomicInteger 这样的数据结构,那么是的,set() 操作意味着强内存顺序,就像 class 中的一些其他操作一样。这里使用 "Atomic" 一词表示 class 实现了一组通常由子操作组成的原子操作(例如 compareAndSet)。顺便说一句,这类数据结构通常遵循强记忆顺序,并且通过单词关联,"atomic" 在这种上下文中使用,通常意味着强记忆顺序。 (但并非总是如此,例如 AtomicInteger 中的 lazySetweakCompareAndSet

回到你的问题,"atomic"这个词没有这个含义,它只是表示写是不可分割的。但那是没有意义的。有意义的是说对非易失性longdouble变量的写入是"non-atomic",因为它相当于两次写入(JLS#17.7)。其他写入不是非原子的。