2

My code contains some AtomicBoolean fields. Only the get() and set() methods of these fields are called.

Can the types of these fields safely be replaced by primitive boolean?

I mean, assignment and access operations of primitive booleans are atomic operations in Java. And from that point of view I cannot see any reason to use AtomicBoolean in my case.

In my understanding AtomicBoolean would only make sense if methods like compareAndSet are used, that combine a comparison and access. Am I wrong about that? Could you explain why?

eztam
  • 3,443
  • 7
  • 36
  • 54
  • 4
    Too broad without showing the code in question, but the general answer is no. – Andy Turner Apr 12 '17 at 21:25
  • 1
    Are you accessing the fields from different threads? – VGR Apr 12 '17 at 21:41
  • there's two types of race conditions: check-then-act and read-modify-write. your problem will be the former if you replace `AtomicBoolean` with a primitive boolean. – mre Apr 12 '17 at 21:41
  • Yes, I'm accessing them from different threads – eztam Apr 12 '17 at 21:41
  • @mre Why should this happen? The code is not using `compareAndSet()` or any similar method. – eztam Apr 12 '17 at 21:44
  • http://stackoverflow.com/questions/34510/what-is-a-race-condition – mre Apr 12 '17 at 21:54
  • @mre Your link explains the check-then-act problem. But why should this be a problem in my case since access and assignment operations of primitive booleans are always atomic in Java and my code does not contain any checks? – eztam Apr 12 '17 at 21:55
  • @eztam, no one reads the field? – mre Apr 12 '17 at 22:01

3 Answers3

5

Atomic variables are described as "better volatiles" in Java Concurrency in Practice (see section 15.3). Here is an extract from this book:

The atomic variable classes provide a generalization of volatile variables to support atomic conditional read-modify-write operations. AtomicInteger represents an int value, and provides get and set methods with the same memory semantics as reads and writes to a volatile int.

Applied to your case this means that if you're using only get() and set() methods of AtomicBoolean, they can be safely replaced with read-writes to volatile boolean.

volatile is needed to guarantee that all threads will see up-to-date value of the variable. Back to Java Concurrency in Practice (section 3.1.4):

When a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Pavlo Viazovskyy
  • 927
  • 5
  • 12
  • Thanks, for your answer. Could you explain why primitive boolean without volatile is not working in my situation? Or could you describe a scenario that could lead to problems when using primitive boolean in my case? – eztam Apr 12 '17 at 22:02
  • 1
    @eztam `AtomicBoolean` is passed as a reference. If you pass a `boolean` to two threads they will no longer have a shared value. – Peter Lawrey Apr 12 '17 at 22:04
  • 2
    @eztam. The only scenario which could lead to problems using primitive `boolean` is using it in _check-then-act_ operations. In this case you should use `AtomicBoolean` (or use synchronization). – Pavlo Viazovskyy Apr 12 '17 at 22:09
  • @PeterLawrey Good point! But I'm just talking about accessing fields from the same class. The AtomicBooleans are not passed anywhere. – eztam Apr 12 '17 at 22:10
  • @Peter. Primitives are shared in the same way as references. You just need to make sure you've declared your primitive as `volatile` so all threads will see up-to-date value. – Pavlo Viazovskyy Apr 12 '17 at 22:13
  • @eztam Do you mean adding my last comment to the answer? – Pavlo Viazovskyy Apr 12 '17 at 22:16
  • I meant the first comment. But why should `volatile` be needed in that case since read and write operations to boolean variables are always atomic https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html – eztam Apr 12 '17 at 22:24
  • 2
    @eztam Volatiles do NOT guarantee _atomicity_. They only guarantee _visibility_. – Pavlo Viazovskyy Apr 12 '17 at 22:50
2

Can the types of these fields safely be replaced by primitive boolean?

Simple primitive boolean is not the same as AtomicBoolean (which provided atomic access in a multi-threaded environment).

But, the safe replacement alternative could be using volatile boolean which would also provide the atomic access, but I suggest you keep the AtomicBoolean as is (because it provides additional API methods, in case if you might it in future).

Vasu
  • 21,832
  • 11
  • 51
  • 67
  • Thanks, the difference between primitive boolean and AtomicBoolean is clear to me. But could you explain why it is not possible to replace them in my individual situation? – eztam Apr 12 '17 at 21:52
  • Can you tell me why do you want to do that? I mean what exactly you are expecting out of it? Because already the access is atomic (as you are using `AtomicBoolean`), so why do you want to change the existing behavior? – Vasu Apr 12 '17 at 21:57
-1

The answer is no. You can find the reasons here Why can't AtomicBoolean be a replacement for Boolean?

Community
  • 1
  • 1
MigSena
  • 218
  • 2
  • 7
  • 2
    That post is about opposite replacement: Replacing `Boolean` with `AtomicBoolean`. – Pavlo Viazovskyy Apr 12 '17 at 21:31
  • Yes. But when you read the provided answer, it is explain that AtomicBoolean is a separate class designed for concurrency purposes. So AtomicBoolean is thread safe. So you cannot replace it by primitive boolean. – MigSena Apr 12 '17 at 21:35
  • In the case you don't want to use AtomicBoolean in your code, you can use a primitive boolean, but you should handle the thread safe property yourself by using synchronisation. – MigSena Apr 12 '17 at 21:37
  • 2
    Reading and writing primitive `volatile boolean` will also be thread safe. `AtomicBoolean` is useful for _check-then-act_ or _compound_ operations which should be performed atomically (e.g. `getAndSet()` or `compareAndSet()`). – Pavlo Viazovskyy Apr 12 '17 at 21:41
  • @PavloViazovskyy I agree with that. But as I explained, the code is not using `getAndSet()` or `compareAndSet()` or something similar. The question is just about the case when only `get()`and `set()` is called. – eztam Apr 12 '17 at 21:46
  • @eztam, the caller of `get()` is not guaranteed to get the most up to date value. – mre Apr 12 '17 at 21:57