How to write a simple thread-safe class using a volatile variable? - java

I want to write a simple thread-safe class that could be used to set or get an Integer value.
The easiest way is to use the synchronized keyword:
public class MyIntegerHolder {
private Integer value;
synchronized public Integer getValue() {
return value;
}
synchronized public void setValue(Integer value) {
this.value = value;
}
}
I could also try using volatile:
public class MyIntegerHolder {
private volatile Integer value;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
Is the class with the volatile keyword thread-safe?
Consider the following sequence of events:
Thread A sets the value to 5.
Thread B sets the value to 7.
Thread C reads the value.
It follows from the Java Language Specification that
"1" happens-before "3"
"2" happens-before "3"
but I don't see how it could follow from the specification that "1" happens-before "2" so I suspect that "1" doesn't happen-before "2".
I suspect the thread C may read 7 or 5. I think the class with the volatile keyword is not thread-safe and the following sequence is also possible:
Thread A sets the value to 5.
Thread B sets the value to 7.
Thread C reads 7.
Thread D reads 5.
Thread C reads 7.
Thread D reads 5.
...
Am I correct in assuming that MyIntegerHolder with volatile is not thread-safe?
Is it possible to make a thread-safe Integer holder by using AtomicInteger:
public class MyIntegerHolder {
private AtomicInteger atomicInteger = new AtomicInteger();
public Integer getValue() {
return atomicInteger.get();
}
public void setValue(Integer value) {
atomicInteger.set(value);
}
}
?
Here is a fragment of the Java Concurrency In Practice book:
"Reads and writes of atomic variables have the same memory semantics
as volatile variables."
What is the best (preferably non-blocking) way of writing a thread-safe MyIntegerHolder?
If you know the answer, I would like to know why you think it is correct. Does it follow from the specification? If so, how?

The keyword synchronized is saying that if Thread A and Thread B want to access the Integer, they cannot do so simultaneously. A is telling B wait until I'm done with it.
On the other hand, volatile makes threads more "friendly". They start talking to each other and working together to perform tasks. So when B tries to access, A will inform B of everything it has done until that moment. B is now aware of the changes and can continue its job from where A left of.
In Java, you have Atomic for this reason, which under the covers use the volatile keyword, so they are doing pretty much the same thing, but they save you time and effort.
The thing you are looking for is AtomicInteger, you are right about this. For the operation you are trying to perform this is the best choice.
There are two main uses of `AtomicInteger`:
* As an atomic counter (incrementAndGet(), etc) that can be used by many threads concurrently
* As a primitive that supports compare-and-swap instruction (compareAndSet()) to implement non-blocking algorithms.
To answer your question on a general note
It depends on what you need. I'm not saying synchronized is wrong and volatile is good, otherwise the nice Java people would have removed synchronized a long time ago. There is no absolute answer, there are a lot of specific cases and usage scenarios.
A few of my bookmarks:
Concurrency tips
Core Java Concurrency
Java concurrency
Update
From the Java Concurrency specification available here:
Package java.util.concurrent.atomic
A small toolkit of classes that support lock-free thread-safe
programming on single variables.
Instances of classes `AtomicBoolean`, `AtomicInteger`, `AtomicLong`, and `AtomicReference` each provide access and updates to a single variable of the corresponding type.
Each class also provides appropriate utility methods for that type.
For example, classes `AtomicLong` and AtomicInteger provide atomic increment methods.
The memory effects for accesses and updates of atomics generally follow the rules for volatiles:
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
Also from Here
The Java programming language volatile keyword:
(In all versions of Java) There is a global ordering on the reads and writes to a volatile variable. This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value. (However, there is no guarantee about the relative ordering of volatile reads and writes with regular reads and writes, meaning that it's generally not a useful threading construct.)

If you need only get / set on a variable it is enough to declare it volatile like you did. If you check how AtomicInteger set / get work you will see the same implementation
private volatile int value;
...
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
but you cannot increment a volatile field atomically this simple. This is where we use AtomicInteger.incrementAndGet or getAndIncrement methods .

Chapter 17 of the Java Language Specification defines the happens-before relation on memory operations such as reads and writes of shared variables. The results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation.
The synchronized and volatile constructs, as well as the Thread.start() and Thread.join() methods, can form happens-before
relationships. In particular: Each action in a thread happens-before
every action in that thread that comes later in the program's order.
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method
entry) of that same monitor. And because the happens-before relation
is transitive, all actions of a thread prior to unlocking
happen-before all actions subsequent to any thread locking that
monitor.
A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar
memory consistency effects as entering and exiting monitors, but do
not entail mutual exclusion locking.
A call to start on a thread happens-before any action in the started thread.
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
reference: http://developer.android.com/reference/java/util/concurrent/package-summary.html
from my understanding 3 means: if you write (not based read result) / read is fine. if you write (based on read result, e.g., increment) / read is not fine. Since volatile "do not entail mutual exclusion locking"

Your MyIntegerHolder with volatile is thread safe. But AtomicInteger is preferred if you are doing concurrent program, because it also provides a lot of atomic operations.
Consider the following sequence of events:
Thread A sets the value to 5.
Thread B sets the value to 7.
Thread C reads the value.
It follows from the Java Language Specification that
"1" happens-before "3"
"2" happens-before "3"
but I don't see how it could follow from the specification that "1"
happens-before "2" so I suspect that "1"
doesn't happen-before "2".
I suspect the thread C may read 7 or 5. I think the class with the
volatile keyword is not thread-safe
You are right here that "1" happens-before "3" and "2" happens-before "3". "1" does not happens-before "2", but it doesn't mean that it is not Thread-safe. The thing is that the example you provided is ambiguous. If you are saying "sets the value to 5", "sets the value to 7", "reads the value" happens sequentially, you can always read the value of 7. And it is nonsense to put them in different threads. But if you are saying that 3 threads executes concurrently without sequence, you can even get value of 0, because "reads the value" could happen first. But this is nothing with Thread-safe, there is no order expecting from the 3 actions.

The question was not easy for me, because I thought (incorrectly) that knowing everything about the happens-before relation gives one a complete understanding of the Java Memory Model - and the semantics of volatile.
I found the best explanation in this document:
"JSR-133: JavaTM Memory Model and Thread Specification"
The most relevant fragment of the above document is the section "7.3 Well-Formed Executions".
The Java Memory Model guarantees that all executions of a program are well-formed. An execution is well-formed only if it
Obeys happens-before consistency
Obeys synchronization-order consistency
... (some other conditions must also be true)
Happens-before consistency is usually enough to come to a conclusion about the program behavior - but not in this case, because a volatile write doesn't happen-before another volatile write.
The MyIntegerHolder with volatile is thread-safe, but it's safety comes from the synchronization-order consistency.
In my opinion when Thread B is about to set the value to 7, A doesn't inform B of everything it has done until that moment (as one of the other answers suggested) - it only informs B about the value of the volatile variable. Thread A would inform B about everything (assigning values to other variables) if the action taken by Thread B was read and not write (in that case, there would exist the happens-before relationship between the actions taken by these two threads).

Related

redundant volatile in cheap read-write lock?

Brian Goetz in his article from https://www.ibm.com/developerworks/java/library/j-jtp06197/
uses the example pasted below as a cheap read-write lock. My question is that if the int variable value is not declared volatile then would it make a difference? My understanding is that since the writes to value are done within a synchronized block so latest value will be visible to other threads any way and therefore declaring it volatile is redundant. Please clarify?
#ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
#GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
My understanding is that since the writes to value are done within a synchronized block so latest value will be visible to other threads any way
This is incorrect. Generally, there is no guarantee that other threads "see" changes to variables as soon as the change is made. A thread may see a stale value for a changed variable because, e.g. the thread sees the value really in a register instead of main memory.
A volatile variable establishes "happens-before" semantics. The JLS, section 17.4.5, states:
Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
The JLS, Section 8.3.1.4:
A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).
The reason that the field must be volatile is that even though the read is atomic, it needs to ensure that the value is current -- that any value previously written by another thread is visible. The read being atomic is not enough; volatile is still necessary to ensure consistency of the value.
public synchronized int increment()
This synchronized prevents you from skipping an increment if two threads or more were trying to increment at the same time (because ++ is not atomic).
private volatile int value
This prevents you from seeing an outdated value in one thread which was already incremented in another thread. (Note that we could also have made getValue synchronized to achieve this)
Thanks very much for the answers guys. Found this on oracle website as well now: "Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object."
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

What happens if a volatile variable is written from 2 threads?

Consider the snippet from Java Concurrency in Practice-
#ThreadSafe
public class SynchronizedInteger{
#GuardedBy("this") private int value;
public synchronized int getValue() {
return value;
}
public synchronized void setValue(int value) {
this.value = value;
}
}
An extract from the same book-
A good way to think about volatile variables is to imagine that they
behave roughly like the SynchronizedInteger class in Listing above,
replacing reads and writes of the volatile variable with calls to get
and set. Yet accessing a volatile variable performs no locking and so
cannot cause the executing thread to block, making volatile variables
a lighter-weight synchronization mechanism than synchronized.
A special case of thread confinement applies to volatile variables. It is safe to perform read-modify-write operations on shared volatile variables as long as you ensure that the volatile variable is only written from a single thread.
So, if you make the instance variable in the above class as volatile and then remove the synchronized keyword, after that suppose there are 3 threads
Thread A & Thread B are writing to the same volatile variable.
Thread C reads the volatile variable.
Since the volatile variable is now written from 2 threads, why is it unsafe to perform read-modify-write operations on this shared volatile variable?
The keyword volatile is used to ensure that changes to your Object will be seen by other Threads.
This does not enforce, that non-atomic operations on the Object will be performed without an other Thread interfering before the operation is finished.
For enforcing this you will need the keyword synchronized.
It's because read-modify-write operations on volatile variables are not atomic. v++ is actually something like:
r1 = v;
r2 = r1 + 1;
v = r2;
So if you have two threads performing this operation once each, it could possibly result in the variable being incremented only once, as they both read the old value. That's an example of why it's not safe.
In your example it would be not safe if you removed synchronized, made the field volatile and had two threads calling setValue after some conditional logic based on the return of getValue - the value could have been modified by the other thread.
If you want atomic operations look at the java.util.concurrent.atomic package.
If you write volatile variable from multiple threads without using any synchronized constructs, you are bound to get data inconsistency errors.
Use volatile variables without synchronization in case of single write thread and multiple read threads for atomic operations.
Volatile make sure that variable value is fetched from main memory instead of Thread cache. It's safe to use in case of single write and multiple read operations.
Use Atomic variables or synchronization or Lock API to update and read variables from multiple threads.
Refer to related SE question:
What is meant by "thread-safe" code?
If two threads are writing without reading the variable first, there is no problem.. it is safe. Problem arises if a thread first reads, then modifies and then writes. What if second thread is also reading at the same time, reads the same old value as the first thread, and modifies it.. and when it writes, it will simply overwrite the first threads update. BOOM.
val i = 1
-> Thread reads 1 -> Threads 2 reads 1 -> Thread 1 does 1 * .2 = 1.2 -> Thread 2 does 1 * .3 = 1.3 -> Thread 1 writes 1.2 back -> Thread 2 cooly overwrites it to 1.3 instead of doing 1.2 * .3

Behavior of memory barrier in Java

After reading more blogs/articles etc, I am now really confused about the behavior of load/store before/after memory barrier.
Following are 2 quotes from Doug Lea in one of his clarification article about JMM, which are both very straighforward:
Anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
Note that it is important for both threads to access the same volatile variable in order to properly set up the happens-before relationship. It is not the case that everything visible to thread A when it writes volatile field f becomes visible to thread B after it reads volatile field g.
But then when I looked into another blog about memory barrier, I got these:
A store barrier, “sfence” instruction on x86, forces all store instructions prior to the barrier to happen before the barrier and have the store buffers flushed to cache for the CPU on which it is issued.
A load barrier, “lfence” instruction on x86, forces all load instructions after the barrier to happen after the barrier and then wait on the load buffer to drain for that CPU.
To me, Doug Lea's clarification is more strict than the other one: basically, it means if the load barrier and store barrier are on different monitors, the data consistency will not be guaranteed. But the later one means even if the barriers are on different monitors, the data consistency will be guaranteed. I am not sure if I understanding these 2 correctly and also I am not sure which of them is correct.
Considering the following codes:
public class MemoryBarrier {
volatile int i = 1, j = 2;
int x;
public void write() {
x = 14; //W01
i = 3; //W02
}
public void read1() {
if (i == 3) { //R11
if (x == 14) //R12
System.out.println("Foo");
else
System.out.println("Bar");
}
}
public void read2() {
if (j == 2) { //R21
if (x == 14) //R22
System.out.println("Foo");
else
System.out.println("Bar");
}
}
}
Let's say we have 1 write thread TW1 first call the MemoryBarrier's write() method, then we have 2 reader threads TR1 and TR2 call MemoryBarrier's read1() and read2() method.Consider this program run on CPU which does not preserve ordering (x86 DO preserve ordering for such cases which is not the case), according to memory model, there will be a StoreStore barrier (let's say SB1) between W01/W02, as well as 2 LoadLoad barrier between R11/R12 and R21/R22 (let's say RB1 and RB2).
Since SB1 and RB1 are on same monitor i, so thread TR1 which calls read1 should always see 14 on x, also "Foo" is always printed.
SB1 and RB2 are on different monitors, if Doug Lea is correct, thread TR2 will not be guaranteed to see 14 on x, which means "Bar" may be printed occasionally. But if memory barrier runs like Martin Thompson described in the blog, the Store barrier will push all data to main memory and Load barrier will pull all data from main memory to cache/buffer, then TR2 will also be guaranteed to see 14 on x.
I am not sure which one is correct, or both of them are but what Martin Thompson described is just for x86 architecture. JMM does not guarantee change to x is visible to TR2 but x86 implementation does.
Thanks~
Doug Lea is right. You can find the relevant part in section §17.4.4 of the Java Language Specification:
§17.4.4 Synchronization Order
[..] A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order). [..]
The memory model of the concrete machine doesn't matter, because the semantics of the Java Programming Language are defined in terms of an abstract machine -- independent of the concrete machine. It's the responsibility of the Java runtime environment to execute the code in such a way, that it complies with the guarantees given by the Java Language Specification.
Regarding the actual question:
If there is no further synchronization, the method read2 can print "Bar", because read2 can be executed before write.
If there is an additional synchronization with a CountDownLatch to make sure that read2 is executed after write, then method read2 will never print "Bar", because the synchronization with CountDownLatch removes the data race on x.
Independent volatile variables:
Does it make sense, that a write to a volatile variable does not synchronize-with a read of any other volatile variable?
Yes, it makes sense. If two threads need to interact with each other, they usually have to use the same volatile variable in order to exchange information. On the other hand, if a thread uses a volatile variable without a need for interacting with all other threads, we don't want to pay the cost for a memory barrier.
It is actually important in practice. Let's make an example. The following class uses a volatile member variable:
class Int {
public volatile int value;
public Int(int value) { this.value = value; }
}
Imagine this class is used only locally within a method. The JIT compiler can easily detect, that the object is only used within this method (Escape analysis).
public int deepThought() {
return new Int(42).value;
}
With the above rule, the JIT compiler can remove all effects of the volatile reads and writes, because the volatile variable can not be accesses from any other thread.
This optimization actually exists in the Java JIT compiler:
src/share/vm/opto/memnode.cpp
As far as I understood the question is actually about volatile read/writes and its happens-before guarantees. Speaking of that part, I have only one thing to add to nosid's answer:
Volatile writes cannot be moved before normal writes, volatile reads cannot be moved after normal reads. That's why read1() and read2() results will be as nosid wrote.
Speaking about barriers - the defininition sounds fine for me, but the one thing that probably confused you is that these are things/tools/way to/mechanism (call it whatever you like) to implement behavior described in JMM in hotspot. When using Java, you should rely on JMM guarantees, not implementation details.

Happens-before relationships with volatile fields and synchronized blocks in Java - and their impact on non-volatile variables?

I am still pretty new to the concept of threading, and try to understand more about it. Recently, I came across a blog post on What Volatile Means in Java by Jeremy Manson, where he writes:
When one thread writes to a volatile variable, and another thread sees
that write, the first thread is telling the second about all of the
contents of memory up until it performed the write to that volatile
variable. [...] all of the memory contents seen by Thread 1, before
it wrote to [volatile] ready, must be visible to Thread 2, after it
reads the value true for ready. [emphasis added by myself]
Now, does that mean that all variables (volatile or not) held in Thread 1's memory at the time of the write to the volatile variable will become visible to Thread 2 after it reads that volatile variable? If so, is it possible to puzzle that statement together from the official Java documentation/Oracle sources? And from which version of Java onwards will this work?
In particular, if all Threads share the following class variables:
private String s = "running";
private volatile boolean b = false;
And Thread 1 executes the following first:
s = "done";
b = true;
And Thread 2 then executes afterwards (after Thread 1 wrote to the volatile field):
boolean flag = b; //read from volatile
System.out.println(s);
Would this be guaranteed to print "done"?
What would happen if instead of declaring b as volatile I put the write and read into a synchronized block?
Additionally, in a discussion entitled "Are static variables shared between threads?", #TREE writes:
Don't use volatile to protect more than one piece of shared state.
Why? (Sorry; I can't comment yet on other questions, or I would have asked there...)
Yes, it is guaranteed that thread 2 will print "done" . Of course, that is if the write to b in Thread 1 actually happens before the read from b in Thread 2, rather than happening at the same time, or earlier!
The heart of the reasoning here is the happens-before relationship. Multithreaded program executions are seen as being made of events. Events can be related by happens-before relationships, which say that one event happens before another. Even if two events are not directly related, if you can trace a chain of happens-before relationships from one event to another, then you can say that one happens before the other.
In your case, you have the following events:
Thread 1 writes to s
Thread 1 writes to b
Thread 2 reads from b
Thread 2 reads from s
And the following rules come into play:
"If x and y are actions of the same thread and x comes before y in program order, then hb(x, y)." (the program order rule)
"A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field." (the volatile rule)
The following happens-before relationships therefore exist:
Thread 1 writes to s happens before Thread 1 writes to b (program order rule)
Thread 1 writes to b happens before Thread 2 reads from b (volatile rule)
Thread 2 reads from b happens before Thread 2 reads from s (program order rule)
If you follow that chain, you can see that as a result:
Thread 1 writes to s happens before Thread 2 reads from s
What would happen if instead of declaring b as volatile I put the write and read into a synchronized block?
If and only if you protect all such synchronized blocks with the same lock will you have the same guarantee of visibility as with your volatile example. You will in addition have mutual exclusion of the execution of such synchronized blocks.
Don't use volatile to protect more than one piece of shared state.
Why?
volatile does not guarantee atomicity: in your example the s variable may also have been mutated by other threads after the write you are showing; the reading thread won't have any guarantee as to which value it sees. Same thing goes for writes to s occurring after your read of the volatile, but before the read of s.
What is safe to do, and done in practice, is sharing immutable state transitively accessible from the reference written to a volatile variable. So maybe that's the meaning intended by "one piece of shared state".
is it possible to puzzle that statement together from the official Java documentation/Oracle sources?
Quotes from the spec:
17.4.4. Synchronization Order
A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).
17.4.5. Happens-before Order
If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
If an action x synchronizes-with a following action y, then we also have hb(x, y).
This should be enough.
And from which version of Java onwards will this work?
Java Language Specification, 3rd Edition introduced the rewrite of the Memory Model specification which is the key to the above guarantees. NB most previous versions acted as if the guarantees were there and many lines of code actually depended on it. People were surprised when they found out that the guarantees had in fact not been there.
Would this be guaranteed to print "done"?
As said in Java Concurrency in Practice:
When thread A writes to a volatile variable and subsequently
thread B reads that same variable, the values of all variables that
were visible to A prior to writing to the volatile variable become
visible to B after reading the volatile variable.
So YES, This guarantees to print "done".
What would happen if instead of declaring b as volatile I put the
write and read into a synchronized block?
This too will guarantee the same.
Don't use volatile to protect more than one piece of shared state.
Why?
Because, volatile guarantees only Visibility. It does'nt guarantee atomicity. If We have two volatile writes in a method which is being accessed by a thread A and another thread B is accessing those volatile variables , then while thread A is executing the method it might be possible that thread A will be preempted by thread B in the middle of operations(e.g. after first volatile write but before second volatile write by the thread A). So to guarantee the atomicity of operation synchronization is the most feasible way out.

AtomicInteger and volatile [duplicate]

This question already has answers here:
What is the difference between atomic / volatile / synchronized?
(7 answers)
Closed 3 years ago.
I know volatile allows for visibility, AtomicInteger allows for atomicity.
So if I use a volatile AtomicInteger, does it mean I don't have to use any more synchronization mechanisms?
Eg.
class A {
private volatile AtomicInteger count;
void someMethod(){
// do something
if(count.get() < 10) {
count.incrementAndGet();
}
}
Is this threadsafe?
I believe that Atomic* actually gives both atomicity and volatility. So when you call (say) AtomicInteger.get(), you're guaranteed to get the latest value. This is documented in the java.util.concurrent.atomic package documentation:
The memory effects for accesses and updates of atomics generally follow the rules for volatiles, as stated in section 17.4 of The Java™ Language Specification.
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
lazySet has the memory effects of writing (assigning) a volatile variable except that it permits reorderings with subsequent (but not previous) memory actions that do not themselves impose reordering constraints with ordinary non-volatile writes. Among other usage contexts, > - lazySet may apply when nulling out, for the sake of garbage collection, a reference that is never accessed again.
weakCompareAndSet atomically reads and conditionally writes a variable but does not create any happens-before orderings, so provides no guarantees with respect to previous or subsequent reads and writes of any variables other than the target of the weakCompareAndSet.
compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
Now if you have
volatile AtomicInteger count;
the volatile part means that each thread will use the latest AtomicInteger reference, and the fact that it's an AtomicInteger means that you'll also see the latest value for that object.
It's not common (IME) to need this - because normally you wouldn't reassign count to refer to a different object. Instead, you'd have:
private final AtomicInteger count = new AtomicInteger();
At that point, the fact that it's a final variable means that all threads will be dealing with the same object - and the fact that it's an Atomic* object means they'll see the latest value within that object.
I'd say no, it's not thread-safe, if you define thread-safe as having the same result under single threaded mode and multithreaded mode. In single threaded mode, the count will never go greater than 10, but in multithreaded mode it can.
The issue is that get and incrementAndGet is atomic but an if is not. Keep in mind that a non-atomic operation can be paused at any time. For example:
count = 9 currently.
Thread A runs if(count.get() <10) and gets true and stopped there.
Thread B runs if(count.get() <10) and gets true too so it runs count.incrementAndGet() and finishes. Now count = 10.
Thread A resumes and runs count.incrementAndGet(), now count = 11 which will never happen in single threaded mode.
If you want to make it thread-safe without using synchronized which is slower, try this implementation instead:
class A{
final AtomicInteger count;
void someMethod(){
// do something
if(count.getAndIncrement() <10){
// safe now
} else count.getAndDecrement(); // rollback so this thread did nothing to count
}
To maintain the original semantics, and support multiple threads, you could do something like:
public class A {
private AtomicInteger count = new AtomicInteger(0);
public void someMethod() {
int i = count.get();
while (i < 10 && !count.compareAndSet(i, i + 1)) {
i = count.get();
}
}
}
This avoids any thread ever seeing count reach 10.
Answer is there in this code
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/atomic/AtomicInteger.java
This is source code of AtomicInteger.
The value is Volatile.
So,AtomicInteger uses Volatile inside.
Your query can be answered in 2 parts, because there are 2 questions in your query :
1)
Referring to Oracle's tutorial documentation for Atomic variables :
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
The java.util.concurrent.atomic package defines classes that support atomic operations on single variables. All classes have get and set methods that work like reads and writes on volatile variables. That is, a set has a happens-before relationship with any subsequent get on the same variable. The atomic compareAndSet method also has these memory consistency features, as do the simple atomic arithmetic methods that apply to integer atomic variables.
So atomic integer does use volatile inside, as other answers here have mentioned. So there's no point in making your atomic integer volatile. You need to synchronize your method.
You should watch John Purcell's free video on Udemy , where he shows the failure of volatile keyword when multiple threads are trying to modify it. Simple and beautiful example.
https://www.udemy.com/course/java-multithreading/learn/lecture/108950#overview
If you change the volatile counter in John's example into an atomic variable, his code is guaranteed to succeed without using sunchronized keyword like he has done in his tutorial
2) Coming to your code :
Say thread 1 kicks into action and "someMethod" does a get and checks for size. It is possible that before getAndIncrement executes(say, by thread 1) , another thread (say thread 2)kicks in and increases the count to 10, and gets out; after which, your thread 1 will resume and increase count to 11. This is erroneous output. This is because your "someMethod" is not protected in anyway from synhronization problems.
I would still recommend you to watch john purcell's videos to see where volatile fails , so that you have a better understanding of the keyword volatile. Replace it with atomicinteger in his example and see the magic.

Categories

Resources