This may seem a very silly question. Consider this:
I have a simple Boolean object with a getter and a setter. Now both of the methods are called from a lot of threads very frequently.
- Do I need to have a synchronization for this boolean?
- Also are Boolean assignments atomic operations?
[UPDA开发者_如何转开发TE]: I know about Atomic Boolean already. I already have a lot of varied solutions, But I was specifically looking for answers and justification of answers for the above 2 question.
No, Boolean access is NOT atomic (on the level of machine code), although it does take "only 1 operation in Java".
Therefore, yes, you do need synchronization for Boolean.
Please see slides 4-6 of this presentation for code examples.
On a related note, you should not synchronize on a Boolean
Yes. But if it's a flag that is written from one thread only and you want to ensure visibility to all threads, then a cheap alternative is using
volatile
.Yes - even though the internal representation of the object (i.e. the actual
boolean
flag inside theBoolean
wrapper) were 64 bit and it could therefore get "split" in a concurrent situation, a boolean can only have one of the two values, right? So plain assignments (get or set) are atomic, but if you're doing anything else (like check-then-act), for instancex = !x
, then it's of course not atomic unless synchronized.
- From a technical perspective, synchronization is not required for writes in one thread to be perceived in another thread. What you do need is a happens-before edge. It is likely that either
volatile
orsynchronized
will be used to achieve the happens-before edge. Both of those techniques result in a synchronized-with edge. So, in practice, you will probably use synchronization to manage the state of your boolean. - Yes. Note that you are not changing the state of the Boolean object. You are only modifying the reference to the Boolean object. Section 17.7 of the language specification states that "writes to and reads of references are always atomic."
Update: Let me expound upon the need for a happens-before edge. Without a happens-before edge, then the changes that one thread makes to the variable are not guaranteed to ever be perceived by the other threads. It is not simply that the change may be perceived at a bad time such as in between a read and a write. The change may never be perceived.
Let's say that we have a boolean variable that we initialize to false. Then we start two threads. The first thread sets the variable to true and stop. The second thread continually checks the variable until it is true, after which it stops. There is no guarantee that the second thread will ever see the variable as true.
Use AtomicBoolean.
No, you don't. But declare the variable
volatile
so that the values are reflected in all threads that are accessing the boolean. If you look atAtomicBoolean
'sset(..)
method, it doesn't have any synchronization either.Yes, practically assignment is atomic. Just setting the value does not need synchronization. However, if you want to do something like:
if (!bool) { bool = false; }
then you need synchronization (or
AtomicBoolean
, which is more efficient than synchronization)
http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html says that read and write of primitive variables is atomic.
Hence it is possible to enforce strict alternation or happens after relationships using boolean (or volatile boolean in case of cache effects)
even if it was atomic there are still syncronization isues since you will propably check the value sometime e.g. if (boolVar==true) -> other thread takes control do_something();
精彩评论