3

I'm new to Java and is currently reading the book Java: A Beginner's Guide, 6th Edition. I come across some confusions with respect to atomicity and memory order in Java.

In the examples of the book that involving multithreading, concurrent access to shared resources (e.g., a shared variable) is not synchronized, nor are the shared resources specifically marked (e.g, atomic or volatile or something like that). For instance, in Try This 15-1 (page 519), concurrent access to the shared variable stopFlag is not serialized nor is the variable specifically marked either.

According to 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 treatment on access to atomic types in C++?

Following are some critical code snippet from the example.

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);
  }
Community
  • 1
  • 1
Lingxi
  • 14,579
  • 2
  • 37
  • 93

2 Answers2

3

As the answer you linked explains, atomicity and visibility are completely different concepts. Atomicity of ints insures that if a thread changes an int value from 5 to -7, other threads may observe either 5 or -7 but never anything else.

Visibility deals with when the other threads are guaranteed to see that the variable changed from 5 to -7.

The example in your book is probably meant to illustrate that unless stopFlag variable is declared as volatile, its modification from one thread may become visible to other threads right away or some indeterminate time later or even never.

Misha
  • 27,433
  • 6
  • 62
  • 78
  • In C++, the common practice to impose memory order is through access to atomic variables (though you can, technically, place thread fences independently, but it is rarely used). So, atomicity and memory order are related at least in C++. The example is to illustrate the basic structure of a Java applet. – Lingxi Aug 12 '15 at 03:22
  • java memory model is a complex enough beast without trying to superimpose it in your mind onto C++ memory model. The terms don't mean the same thing. There are no atomic variables in java although there are classes like `AtomicInteger` that wrap around `volatile` variables and provide a nice API to work with them. – Misha Aug 12 '15 at 03:32
  • @Lingxi If that example in the book is to illustrate how you are supposed to write thread-safe code, get a better book. "Effective Java" is a fantastic all-around Java book. If you are especially interested in concurrency and memory model, "Java Concurrency in Practice" has all the information you will ever need. – Misha Aug 12 '15 at 03:38
  • Thanks for your suggestions. I will look into those books. – Lingxi Aug 12 '15 at 03:45
  • @Lingxi, in C++ this practice works because the designers gave atomic variables additional semantics such that operations are sequentially consistent by default. This doesn't have to be the case in every language, it's not even the case in C++ if you explicitly pick other consistency models. See - http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/ – Leeor Aug 12 '15 at 18:32
3

No.

If you use data structures like AtomicInteger, then yes, set() operation implies a strong memory order, just like some other operations in the class. The word "Atomic" is used here to express that the class implement a set of atomic operations (e.g. compareAndSet) that ordinarily would be composed of sub-operations. Incidentally, these kind of data structures often follow strong memory orders, and by word association, "atomic", used in this kind of context, often implies strong memory order. (But not always true though, e.g. lazySet and weakCompareAndSet in AtomicInteger)

Back to your question, the word "atomic" there has no such connotation, it simply means the write is indivisible. But that is meaningless. What is meaningful is to say that a write to a non-volatile long or double variable is "non-atomic" because it is equivalent to two writes (JLS#17.7). Other writes are not-non-atomic.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • Your answer agrees with my understanding and expectations :) In C++, the difference is that when applying operations on atomic types, you have a choice as to what kind of memory order (fence) to impose (with the most strict sequential-consistency being default). – Lingxi Aug 12 '15 at 03:44
  • This article (http://www.infoq.com/articles/memory_barriers_jvm_concurrency) seems to confirm this point. Gonna accept this answer. – Lingxi Aug 12 '15 at 04:27
  • see also section#6 of this paper - http://soft.vub.ac.be/races/wp-content/uploads/2012/09/races2012_submission_3.pdf – ZhongYu Aug 12 '15 at 04:36