1

I have a multithreaded application where I need to ensure all threads are referring to the latest version of a long. I was thinking of using AtomicLong for this purpose. The AtomicLong will be in one class and other classes will need to get the value and also set the value.

private final AtomicLong key;

public ClassHoldingLong(){
this.key = new AtomicLong(System.currenttimemillis());
}

public long getKey() {
    return key.get();
}

public void setKey(long key) {
    this.key.set(key);
}

Is this fine to do or should the getter be AtomicLong itself and someone calls .get() on the AtomicLong rather than this class holding the variable calling it for another class. From what I read, these getters setters don't need to be synchronized but not sure if that is only if AtomicLong is the return type.

This class does have additional information it holds such as statistics and additional functionality. I just included this snippet of code for an example

Kirit
  • 389
  • 2
  • 3
  • 11
  • Just make the variable public? No point in the extra boilerplate, really. – Mick Mnemonic Apr 27 '18 at 20:51
  • 4
    As-is, it is fine. If you would return the `AtomicLong`, you would leak the object-internal state to the outside world (which is most likely not wat you want). As an aside: If you only need to guarantee that a current value is read and the value is not modified concurrently, a `volatile long` would be sufficient. – Turing85 Apr 27 '18 at 20:52
  • The whole point seems to be using an atomic long, so it's leaking in any case. – Mick Mnemonic Apr 27 '18 at 20:53
  • If the purpose of this class is to only hold the AtomicLong, then this is overkill and you should just use the AtomicLong directly. If the class serves a purpose to hold other data and perform additional functionality, then this pattern seems like a good solution to me. – Code-Apprentice Apr 27 '18 at 20:53
  • I see no added value by wrapping `AtomicLong` additionaly. – lexicore Apr 27 '18 at 20:53
  • @Turing85, wouldn't this implementation actually be _incorrect_, i.e. the operations would no longer be _atomic_ when wrapped within method calls (without synchronization) and you'd introduce race conditions? – Mick Mnemonic Apr 27 '18 at 20:59
  • @Turing85 Oh interesting, I had thought using volatile on long values do not work in java which is why we need to use AtomicLong. Perhaps though volatile Long doesn't work and my understanding was incorrect – Kirit Apr 27 '18 at 21:00
  • @MickMnemonic ["*Reads and writes are atomic for all variables declared `volatile` (including `long` and `double` variables).*"](https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html) – Turing85 Apr 27 '18 at 21:02
  • `volatile` works with long and double. You are probably thinking of [non-atomic treatment of *non*-`volatile` longs and doubles.](https://docs.oracle.com/javase/specs/jls/se9/html/jls-17.html#jls-17.7) The main benefit of `AtomicLong` is that it provides CAS utilities (`compareAndSet`, `getAndIncrement`, `updateAndGet`, etc.). – Radiodef Apr 27 '18 at 21:03
  • @Radiodef you are right. Got confused for a second. Baseline: As-is, a `volatile long` seems to be sufficient (as long as not more complex operations are used). – Turing85 Apr 27 '18 at 21:04
  • @Turing85, I was referring to OP's implementation of `getKey()`/ `setKey(long key)` (which you say is OK as-is). That is no longer atomic. – Mick Mnemonic Apr 27 '18 at 21:05
  • @MickMnemonic declaring `key` as `volatile long` will have the same "level of atomicity" as it has now. The method can be called mutliple times, but the *effect* will be atomic, i.e. you introduce a happens-before order. – Turing85 Apr 27 '18 at 21:07

0 Answers0