6

I'm wondering if a getter method for a private boolean field forces the other threads to get the latest updated value? Is this an alternative for volatile field? For example:

Class A {
    private boolean flag;

    public boolean getFlag() {
        return this.flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

vs

Class B {
    public volatile boolean flag;
}

Edit: Is it true that the entire object is cached by a thread (including the private field), so that when I call the getter it will return the cached private field?

  • 4
    No. These two are in no way equivalent. Why would you think that they are? Logically; if `volatile` were the same as a getter then why would we need an entirely new language keyword for it? – Boris the Spider Apr 08 '17 at 12:13
  • As I said, I think the getter forces a thread to get an uncached value. Why isn't a getter taking the last updated value? –  Apr 08 '17 at 12:14
  • Maybe you need to see [JLS](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4). – holi-java Apr 08 '17 at 12:16
  • 1
    *"I think the getter forces a thread to get an uncached value."* What makes you think that? Do you have any reference for it? I'm not aware of anything along those lines. – T.J. Crowder Apr 08 '17 at 12:16
  • 1
    @ovidiu-miu if every reference to a local variable from a method caused a full cache miss to main memory (i.e. a memory barrier) then Java would not be a very efficient language. It would, in fact, be up to **300(!)** times slower than it currently is... – Boris the Spider Apr 08 '17 at 12:17
  • Why would a getter take the value from cache, and not rather from the 'source'? –  Apr 08 '17 at 12:18
  • 2
    For the same reason any other method would read from a cache: to be more efficient. 99.99% of the variables are accessed by a single thread. When they are not, you need to apply proper synchronization to access them. Volatile is one of those synchronization techniques. – JB Nizet Apr 08 '17 at 12:24
  • 1
    Because reading from CPU cache *is the default* - special instructions have to be inserted to force synchronization – Joni Apr 08 '17 at 12:37
  • You are asking the equivalent of "are curtains an alternative to a table?" They're not even remotely related. – Joe C Apr 08 '17 at 12:59
  • @JoeC Not really. Maybe the question is too subtle. –  Apr 08 '17 at 13:01
  • @JoeC isn't far off. Hopefully the answer you have accepted explains why. If not, then I would suggest you read the wonderful [JCIP](http://jcip.net/). – Boris the Spider Apr 08 '17 at 13:14

4 Answers4

5

No, getter will not cause the field to be synchronized.

when talking about reading and writing a primitive in a multi-threaded environment, we have three problems, caused by the CPU

  1. Atomicity : it may require the store or load operation more than one assembly instruction, for example, writin into a 64-bit integer on a 32-bit CPU. the current thread may be put to sleep by the operating system in the middle of the instruction sequence.
  2. Visibility : a thread that runs on one core may not read the latest value that other thread from other core has written. simply because the CPU says so.
  3. Reordering : in order to make the program run faster, the CPU blends the order of the assembly instructions as it sees fit.

Getter doesn't solve any of these problem. even if it was, the JIT compiler may completely optimize that function away. than what?

Volatile is one of the ways to solve of the problems above. so does a lock. they ensure that one thread reads the latest value of the primitive, or make sure that a value being written is visible to other threads. they also cause the assembly instructions to run exactly as they were compiled, without any blending.

As a side note, the generated assembly may look completely different from what you have written in your code. you ask yourself "I wrote in my code to read from flag, so why wouldn't the program read from the field itself?" the compiler may do whatever it sees fit to make the assembly fast as possible. by not adding any locks or volatile specifier, you basically told the compiler that no multi-threaded access is involved and the compiler (and subsequently, the CPU) is free to assume that the object is not touched by multiple threads. it could be that this object may not be created at the first place. the JIT compiler may say "well, declare this boolean in a register and treat that as the entire object". it is very possible.

Edit: Is it true that the entire object is cached by a thread (including the private field), so that when I call the getter it will return the cached private field?

You cannot assume that. it is up to the JVM, the underlying OS and the underlying CPU. it may be cached completely, partially or not at all. to remind you, most of the CPU's out there have more than one cache line, even if the object is cached, where is it cached? in the registers or one of the cache lines?

David Haim
  • 25,446
  • 3
  • 44
  • 78
  • "_Java solves the first problem_" - see [JLS 17.6](https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.6); reading and writing of a non-volatile 64 bit value is not guaranteed to be atomic. – Boris the Spider Apr 08 '17 at 13:07
  • @BoristheSpider also, what about out of thin air guarantee? – David Haim Apr 08 '17 at 13:09
  • See [this answer](http://stackoverflow.com/a/21243924/2071828). The thread may see partially updated data - the point is that it isn't _random_ data. – Boris the Spider Apr 08 '17 at 13:10
1

I'm wondering if a getter method for a private boolean field forces the other threads to get the latest updated value

No. It does not force other threads to get the latest value in absence of volatile keyword.

Is this an alternative for volatile field?

No. Simple getter call is not alternative to get latest value of boolean value in absence of volatile keyword.

Better solution to solve your problem : Use AtomicBoolean

A boolean value that may be updated atomically. See the java.util.concurrent.atomic package specification for description of the properties of atomic variables.

Few more useful links:

Atomic package-summary

What is the difference between atomic / volatile / synchronized?

Community
  • 1
  • 1
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
0

getter forces a thread to get an uncached value? Is this an alternative for volatile field?

No, getter method doesn't force anything, so you must need a volatile so that the current thread sees the latest value updated by the other threads, otherwise, you might see the stale values.

You need to know the below text from here and understand the concept of atomic access clearly.

volatile variable are always visible to other threads. It also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile

Vasu
  • 21,832
  • 11
  • 51
  • 67
  • Isn't a getter method supposed to get the real value? Or is it that the entire object is cached (including the private field), so that when I call the getter it will return the cached private field? –  Apr 08 '17 at 12:25
  • 1
    @ovidiu-miu a "getter" is in no way special. It's simply a method, like any other. It takes arguments and returns a value. When a variable is read by multiple threads, those reads may be inconsistent. Full stop. – Boris the Spider Apr 08 '17 at 12:26
0

If you use synchronized keyword with the two methods then yes:

public synchronized boolean getFlag() {
    return this.flag;
}

public synchronized void setFlag(boolean flag) {
    this.flag = flag;
}

Then these two methods are equivalent to using volatile on the instance variable