When to use AtomicReference in Java?
When do we use AtomicReference?
Is it needed to create objects in all multithreaded programs?
Provide a simple example where AtomicReference should be used.
java multithreading
add a comment |
When do we use AtomicReference?
Is it needed to create objects in all multithreaded programs?
Provide a simple example where AtomicReference should be used.
java multithreading
add a comment |
When do we use AtomicReference?
Is it needed to create objects in all multithreaded programs?
Provide a simple example where AtomicReference should be used.
java multithreading
When do we use AtomicReference?
Is it needed to create objects in all multithreaded programs?
Provide a simple example where AtomicReference should be used.
java multithreading
java multithreading
edited Dec 19 '16 at 14:01


Ravindra babu
29.7k5161136
29.7k5161136
asked Oct 18 '10 at 23:15
ChintuChintu
1,218294
1,218294
add a comment |
add a comment |
8 Answers
8
active
oldest
votes
Atomic reference should be used in a setting where you need to do simple atomic (i.e. thread safe, non-trivial) operations on a reference, for which monitor-based synchronization is not appropriate. Suppose you want to check to see if a specific field only if the state of the object remains as you last checked:
AtomicReference<Object> cache = new AtomicReference<Object>();
Object cachedValue = new Object();
cache.set(cachedValue);
//... time passes ...
Object cachedValueToUpdate = cache.get();
//... do some work to transform cachedValueToUpdate into a new version
Object newValue = someFunctionOfOld(cachedValueToUpdate);
boolean success = cache.compareAndSet(cachedValue,cachedValueToUpdate);
Because of the atomic reference semantics, you can do this even if the cache
object is shared amongst threads, without using synchronized
. In general, you're better off using synchronizers or the java.util.concurrent
framework rather than bare Atomic*
unless you know what you're doing.
Two excellent dead-tree references which will introduce you to this topic:
- Herlihy's excellent Art of Multiprocessor Programming
- Java Concurrency in Practice
Note that (I don't know if this has always been true) reference assignment (i.e. =
) is itself atomic (updating primitive 64-bit types like long
or double
may not be atomic; but updating a reference is always atomic, even if it's 64 bit) without explicitly using an Atomic*
.
See the Java Language Specification 3ed, Section 17.7.
33
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
4
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
24
@sMoZely That is correct, but if you're not usingAtomicReference
you should mark the variablevolatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.
– kbolino
Mar 14 '14 at 17:51
1
@BradCupit note that I said "if you're not usingAtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark itfinal
so the compiler can optimize accordingly.
– kbolino
Feb 19 '15 at 2:26
|
show 2 more comments
An atomic reference is ideal to use when you need to share and change the state of an immutable object between multiple threads. That is a super dense statement so I will break it down a bit.
First, an immutable object is an object that is effectively not changed after construction. Frequently an immutable object's methods return new instances of that same class. Some examples include the wrapper classes of Long and Double, as well as String, just to name a few. (According to Programming Concurrency on the JVM immutable objects are a critical part of modern concurrency).
Next, why AtomicReference is better than a volatile object for sharing that shared value. A simple code example will show the difference.
volatile String sharedValue;
static final Object lock=new Object();
void modifyString(){
synchronized(lock){
sharedValue=sharedValue+"something to add";
}
}
Every time you want to modify the string referenced by that volatile field based on its current value, you first need to obtain a lock on that object. This prevents some other thread from coming in during the meantime and changing the value in the middle of the new string concatenation. Then when your thread resumes, you clobber the work of the other thread. But honestly that code will work, it looks clean, and it would make most people happy.
Slight problem. It is slow. Especially if there is a lot of contention of that lock Object. Thats because most locks require an OS system call, and your thread will block and be context switched out of the CPU to make way for other processes.
The other option is to use an AtomicRefrence.
public static AtomicReference<String> shared = new AtomicReference<>();
String init="Inital Value";
shared.set(init);
//now we will modify that value
boolean success=false;
while(!success){
String prevValue=shared.get();
// do all the work you need to
String newValue=shared.get()+"lets add something";
// Compare and set
success=shared.compareAndSet(prevValue,newValue);
}
Now why is this better? Honestly that code is a little less clean than before. But there is something really important that happens under the hood in AtomicRefrence, and that is compare and swap.
It is a single CPU instruction, not an OS call, that makes the switch happen. That is a single instruction on the CPU. And because there are no locks, there is no context switch in the case where the lock gets exercised which saves even more time!
The catch is, for AtomicReferences, this does not use a .equals() call, but instead an == comparison for the expected value. So make sure the expected is the actual object returned from get in the loop.
14
Your two examples behave differently. You'd have to loop onworked
to get the same semantics.
– CurtainDog
Oct 13 '14 at 20:32
4
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
6
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
@CurtainDog Loop to hope thatshared
might becomeprevValue
again? Good luck :)
– Ivan Balashov
Jul 14 '16 at 6:52
2
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
|
show 1 more comment
Here is a use case for AtomicReference:
Consider this class that acts as a number range, and uses individual AtmomicInteger variables to maintain lower and upper number bounds.
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
// Warning -- unsafe check-then-act
if (i > upper.get())
throw new IllegalArgumentException(
"can't set lower to " + i + " > upper");
lower.set(i);
}
public void setUpper(int i) {
// Warning -- unsafe check-then-act
if (i < lower.get())
throw new IllegalArgumentException(
"can't set upper to " + i + " < lower");
upper.set(i);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
}
Both setLower and setUpper are check-then-act sequences, but they do not use sufficient locking to make them atomic. If the number range holds (0, 10), and one thread calls setLower(5) while another thread calls setUpper(4), with some unlucky timing both will pass the checks in the setters and both modifications will be applied. The result is that the range now holds (5, 4)an invalid state. So while the underlying AtomicIntegers are thread-safe, the composite class is not. This can be fixed by using a AtomicReference instead of using individual AtomicIntegers for upper and lower bounds.
public class CasNumberRange {
//Immutable
private static class IntPair {
final int lower; // Invariant: lower <= upper
final int upper;
...
}
private final AtomicReference<IntPair> values =
new AtomicReference<IntPair>(new IntPair(0, 0));
public int getLower() { return values.get().lower; }
public int getUpper() { return values.get().upper; }
public void setLower(int i) {
while (true) {
IntPair oldv = values.get();
if (i > oldv.upper)
throw new IllegalArgumentException(
"Can't set lower to " + i + " > upper");
IntPair newv = new IntPair(i, oldv.upper);
if (values.compareAndSet(oldv, newv))
return;
}
}
// similarly for setUpper
}
1
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
add a comment |
You can use AtomicReference when applying optimistic locks. You have a shared object and you want to change it from more than 1 thread.
- You can create a copy of the shared object
- Modify the shared object
- You need to check that the shared object is still the same as before - if yes, then update with the reference of the modified copy.
As other thread might have modified it and/can modify between these 2 steps. You need to do it in an atomic operation. this is where AtomicReference can help
add a comment |
Here's a very simple use case and has nothing to do with thread safety.
To share an object between lambda invocations, the AtomicReference
is an option:
public void doSomethingUsingLambdas() {
AtomicReference<YourObject> yourObjectRef = new AtomicReference<>();
soSomethingThatTakesALambda(() -> {
yourObjectRef.set(youObject);
});
soSomethingElseThatTakesALambda(() -> {
YourObject yourObject = yourObjectRef.get();
});
}
I'm not saying this is good design or anything (it's just a trivial example), but if you have have the case where you need to share an object between lambda invocations, the AtomicReference
is an option.
In fact you can use any object that holds a reference, even a Collection that has only one item. However, the AtomicReference is a perfect fit.
add a comment |
I won't talk much. Already my respected fellow friends have given their valuable input. The full fledged running code at the last of this blog should remove any confusion. It's about a movie seat booking small program in multi-threaded scenario.
Some important elementary facts are as follows.
1> Different threads can only contend for instance and static member variables in the heap space.
2> Volatile read or write are completely atomic and serialized/happens before and only done from memory. By saying this I mean that any read will follow the previous write in memory. And any write will follow the previous read from memory. So any thread working with a volatile will always see the most up-to-date value.
AtomicReference uses this property of volatile.
Following are some of the source code of AtomicReference.
AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between.
As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the full running code.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Solution {
static List<AtomicReference<Integer>> seats;// Movie seats numbered as per
// list index
public static void main(String args) throws InterruptedException {
// TODO Auto-generated method stub
seats = new ArrayList<>();
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
for (Thread t : ths) {
t.join();
}
for (AtomicReference<Integer> seat : seats) {
System.out.print(" " + seat.get());
}
}
/**
* id is the id of the user
*
* @author sankbane
*
*/
static class MyTh extends Thread {// each thread is a user
static AtomicInteger full = new AtomicInteger(0);
List<AtomicReference<Integer>> l;//seats
int id;//id of the users
int seats;
public MyTh(List<AtomicReference<Integer>> list, int userId) {
l = list;
this.id = userId;
seats = list.size();
}
@Override
public void run() {
boolean reserved = false;
try {
while (!reserved && full.get() < seats) {
Thread.sleep(50);
int r = ThreadLocalRandom.current().nextInt(0, seats);// excludes
// seats
//
AtomicReference<Integer> el = l.get(r);
reserved = el.compareAndSet(null, id);// null means no user
// has reserved this
// seat
if (reserved)
full.getAndIncrement();
}
if (!reserved && full.get() == seats)
System.out.println("user " + id + " did not get a seat");
} catch (InterruptedException ie) {
// log it
}
}
}
}
add a comment |
When do we use AtomicReference?
AtomicReference is flexible way to update the variable value atomically without use of synchronization.
AtomicReference
support lock-free thread-safe programming on single variables.
There are multiple ways of achieving Thread safety with high level concurrent API. Atomic variables is one of the multiple options.
Lock
objects support locking idioms that simplify many concurrent applications.
Executors
define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
Provide a simple example where AtomicReference should be used.
Sample code with AtomicReference
:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
Is it needed to create objects in all multithreaded programs?
You don't have to use AtomicReference
in all multi threaded programs.
If you want to guard a single variable, use AtomicReference
. If you want to guard a code block, use other constructs like Lock
/synchronized
etc.
add a comment |
Another simple example is to do a safe-thread modification in a session object.
public PlayerScore getHighScore() {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
return holder.get();
}
public void updateHighScore(PlayerScore newScore) {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
while (true) {
HighScore old = holder.get();
if (old.score >= newScore.score)
break;
else if (holder.compareAndSet(old, newScore))
break;
}
}
Source: http://www.ibm.com/developerworks/library/j-jtp09238/index.html
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f3964211%2fwhen-to-use-atomicreference-in-java%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
Atomic reference should be used in a setting where you need to do simple atomic (i.e. thread safe, non-trivial) operations on a reference, for which monitor-based synchronization is not appropriate. Suppose you want to check to see if a specific field only if the state of the object remains as you last checked:
AtomicReference<Object> cache = new AtomicReference<Object>();
Object cachedValue = new Object();
cache.set(cachedValue);
//... time passes ...
Object cachedValueToUpdate = cache.get();
//... do some work to transform cachedValueToUpdate into a new version
Object newValue = someFunctionOfOld(cachedValueToUpdate);
boolean success = cache.compareAndSet(cachedValue,cachedValueToUpdate);
Because of the atomic reference semantics, you can do this even if the cache
object is shared amongst threads, without using synchronized
. In general, you're better off using synchronizers or the java.util.concurrent
framework rather than bare Atomic*
unless you know what you're doing.
Two excellent dead-tree references which will introduce you to this topic:
- Herlihy's excellent Art of Multiprocessor Programming
- Java Concurrency in Practice
Note that (I don't know if this has always been true) reference assignment (i.e. =
) is itself atomic (updating primitive 64-bit types like long
or double
may not be atomic; but updating a reference is always atomic, even if it's 64 bit) without explicitly using an Atomic*
.
See the Java Language Specification 3ed, Section 17.7.
33
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
4
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
24
@sMoZely That is correct, but if you're not usingAtomicReference
you should mark the variablevolatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.
– kbolino
Mar 14 '14 at 17:51
1
@BradCupit note that I said "if you're not usingAtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark itfinal
so the compiler can optimize accordingly.
– kbolino
Feb 19 '15 at 2:26
|
show 2 more comments
Atomic reference should be used in a setting where you need to do simple atomic (i.e. thread safe, non-trivial) operations on a reference, for which monitor-based synchronization is not appropriate. Suppose you want to check to see if a specific field only if the state of the object remains as you last checked:
AtomicReference<Object> cache = new AtomicReference<Object>();
Object cachedValue = new Object();
cache.set(cachedValue);
//... time passes ...
Object cachedValueToUpdate = cache.get();
//... do some work to transform cachedValueToUpdate into a new version
Object newValue = someFunctionOfOld(cachedValueToUpdate);
boolean success = cache.compareAndSet(cachedValue,cachedValueToUpdate);
Because of the atomic reference semantics, you can do this even if the cache
object is shared amongst threads, without using synchronized
. In general, you're better off using synchronizers or the java.util.concurrent
framework rather than bare Atomic*
unless you know what you're doing.
Two excellent dead-tree references which will introduce you to this topic:
- Herlihy's excellent Art of Multiprocessor Programming
- Java Concurrency in Practice
Note that (I don't know if this has always been true) reference assignment (i.e. =
) is itself atomic (updating primitive 64-bit types like long
or double
may not be atomic; but updating a reference is always atomic, even if it's 64 bit) without explicitly using an Atomic*
.
See the Java Language Specification 3ed, Section 17.7.
33
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
4
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
24
@sMoZely That is correct, but if you're not usingAtomicReference
you should mark the variablevolatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.
– kbolino
Mar 14 '14 at 17:51
1
@BradCupit note that I said "if you're not usingAtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark itfinal
so the compiler can optimize accordingly.
– kbolino
Feb 19 '15 at 2:26
|
show 2 more comments
Atomic reference should be used in a setting where you need to do simple atomic (i.e. thread safe, non-trivial) operations on a reference, for which monitor-based synchronization is not appropriate. Suppose you want to check to see if a specific field only if the state of the object remains as you last checked:
AtomicReference<Object> cache = new AtomicReference<Object>();
Object cachedValue = new Object();
cache.set(cachedValue);
//... time passes ...
Object cachedValueToUpdate = cache.get();
//... do some work to transform cachedValueToUpdate into a new version
Object newValue = someFunctionOfOld(cachedValueToUpdate);
boolean success = cache.compareAndSet(cachedValue,cachedValueToUpdate);
Because of the atomic reference semantics, you can do this even if the cache
object is shared amongst threads, without using synchronized
. In general, you're better off using synchronizers or the java.util.concurrent
framework rather than bare Atomic*
unless you know what you're doing.
Two excellent dead-tree references which will introduce you to this topic:
- Herlihy's excellent Art of Multiprocessor Programming
- Java Concurrency in Practice
Note that (I don't know if this has always been true) reference assignment (i.e. =
) is itself atomic (updating primitive 64-bit types like long
or double
may not be atomic; but updating a reference is always atomic, even if it's 64 bit) without explicitly using an Atomic*
.
See the Java Language Specification 3ed, Section 17.7.
Atomic reference should be used in a setting where you need to do simple atomic (i.e. thread safe, non-trivial) operations on a reference, for which monitor-based synchronization is not appropriate. Suppose you want to check to see if a specific field only if the state of the object remains as you last checked:
AtomicReference<Object> cache = new AtomicReference<Object>();
Object cachedValue = new Object();
cache.set(cachedValue);
//... time passes ...
Object cachedValueToUpdate = cache.get();
//... do some work to transform cachedValueToUpdate into a new version
Object newValue = someFunctionOfOld(cachedValueToUpdate);
boolean success = cache.compareAndSet(cachedValue,cachedValueToUpdate);
Because of the atomic reference semantics, you can do this even if the cache
object is shared amongst threads, without using synchronized
. In general, you're better off using synchronizers or the java.util.concurrent
framework rather than bare Atomic*
unless you know what you're doing.
Two excellent dead-tree references which will introduce you to this topic:
- Herlihy's excellent Art of Multiprocessor Programming
- Java Concurrency in Practice
Note that (I don't know if this has always been true) reference assignment (i.e. =
) is itself atomic (updating primitive 64-bit types like long
or double
may not be atomic; but updating a reference is always atomic, even if it's 64 bit) without explicitly using an Atomic*
.
See the Java Language Specification 3ed, Section 17.7.
edited Apr 3 '18 at 11:56


informatik01
13.1k85589
13.1k85589
answered Oct 18 '10 at 23:22
andersojandersoj
17.3k64971
17.3k64971
33
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
4
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
24
@sMoZely That is correct, but if you're not usingAtomicReference
you should mark the variablevolatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.
– kbolino
Mar 14 '14 at 17:51
1
@BradCupit note that I said "if you're not usingAtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark itfinal
so the compiler can optimize accordingly.
– kbolino
Feb 19 '15 at 2:26
|
show 2 more comments
33
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
4
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
24
@sMoZely That is correct, but if you're not usingAtomicReference
you should mark the variablevolatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.
– kbolino
Mar 14 '14 at 17:51
1
@BradCupit note that I said "if you're not usingAtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark itfinal
so the compiler can optimize accordingly.
– kbolino
Feb 19 '15 at 2:26
33
33
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Correct me if I'm wrong, but it seems like the key to needing this is because you need to do a "compareAndSet". If all I needed to do was set I wouldn't need the AtomicObject at all because of reference updates themselves being atomic?
– sMoZely
Jan 20 '13 at 21:46
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
Is it safe to do cache.compareAndSet(cachedValue, someFunctionOfOld(cachedValueToUpdate))? I.e. inline the computation?
– kaqqao
Dec 10 '13 at 12:07
4
4
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
@veggen Function arguments in Java are evaluated before function itself, so inlining makes no difference in this case. Yes, it is safe.
– Dmitry
Feb 19 '14 at 12:54
24
24
@sMoZely That is correct, but if you're not using
AtomicReference
you should mark the variable volatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.– kbolino
Mar 14 '14 at 17:51
@sMoZely That is correct, but if you're not using
AtomicReference
you should mark the variable volatile
because while the runtime guarantees that reference assignment is atomic, the compiler may perform optimizations under the assumption that the variable was not being modified by other threads.– kbolino
Mar 14 '14 at 17:51
1
1
@BradCupit note that I said "if you're not using
AtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark it final
so the compiler can optimize accordingly.– kbolino
Feb 19 '15 at 2:26
@BradCupit note that I said "if you're not using
AtomicReference
"; if you are using it, then my advice would be to go in the opposite direction and mark it final
so the compiler can optimize accordingly.– kbolino
Feb 19 '15 at 2:26
|
show 2 more comments
An atomic reference is ideal to use when you need to share and change the state of an immutable object between multiple threads. That is a super dense statement so I will break it down a bit.
First, an immutable object is an object that is effectively not changed after construction. Frequently an immutable object's methods return new instances of that same class. Some examples include the wrapper classes of Long and Double, as well as String, just to name a few. (According to Programming Concurrency on the JVM immutable objects are a critical part of modern concurrency).
Next, why AtomicReference is better than a volatile object for sharing that shared value. A simple code example will show the difference.
volatile String sharedValue;
static final Object lock=new Object();
void modifyString(){
synchronized(lock){
sharedValue=sharedValue+"something to add";
}
}
Every time you want to modify the string referenced by that volatile field based on its current value, you first need to obtain a lock on that object. This prevents some other thread from coming in during the meantime and changing the value in the middle of the new string concatenation. Then when your thread resumes, you clobber the work of the other thread. But honestly that code will work, it looks clean, and it would make most people happy.
Slight problem. It is slow. Especially if there is a lot of contention of that lock Object. Thats because most locks require an OS system call, and your thread will block and be context switched out of the CPU to make way for other processes.
The other option is to use an AtomicRefrence.
public static AtomicReference<String> shared = new AtomicReference<>();
String init="Inital Value";
shared.set(init);
//now we will modify that value
boolean success=false;
while(!success){
String prevValue=shared.get();
// do all the work you need to
String newValue=shared.get()+"lets add something";
// Compare and set
success=shared.compareAndSet(prevValue,newValue);
}
Now why is this better? Honestly that code is a little less clean than before. But there is something really important that happens under the hood in AtomicRefrence, and that is compare and swap.
It is a single CPU instruction, not an OS call, that makes the switch happen. That is a single instruction on the CPU. And because there are no locks, there is no context switch in the case where the lock gets exercised which saves even more time!
The catch is, for AtomicReferences, this does not use a .equals() call, but instead an == comparison for the expected value. So make sure the expected is the actual object returned from get in the loop.
14
Your two examples behave differently. You'd have to loop onworked
to get the same semantics.
– CurtainDog
Oct 13 '14 at 20:32
4
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
6
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
@CurtainDog Loop to hope thatshared
might becomeprevValue
again? Good luck :)
– Ivan Balashov
Jul 14 '16 at 6:52
2
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
|
show 1 more comment
An atomic reference is ideal to use when you need to share and change the state of an immutable object between multiple threads. That is a super dense statement so I will break it down a bit.
First, an immutable object is an object that is effectively not changed after construction. Frequently an immutable object's methods return new instances of that same class. Some examples include the wrapper classes of Long and Double, as well as String, just to name a few. (According to Programming Concurrency on the JVM immutable objects are a critical part of modern concurrency).
Next, why AtomicReference is better than a volatile object for sharing that shared value. A simple code example will show the difference.
volatile String sharedValue;
static final Object lock=new Object();
void modifyString(){
synchronized(lock){
sharedValue=sharedValue+"something to add";
}
}
Every time you want to modify the string referenced by that volatile field based on its current value, you first need to obtain a lock on that object. This prevents some other thread from coming in during the meantime and changing the value in the middle of the new string concatenation. Then when your thread resumes, you clobber the work of the other thread. But honestly that code will work, it looks clean, and it would make most people happy.
Slight problem. It is slow. Especially if there is a lot of contention of that lock Object. Thats because most locks require an OS system call, and your thread will block and be context switched out of the CPU to make way for other processes.
The other option is to use an AtomicRefrence.
public static AtomicReference<String> shared = new AtomicReference<>();
String init="Inital Value";
shared.set(init);
//now we will modify that value
boolean success=false;
while(!success){
String prevValue=shared.get();
// do all the work you need to
String newValue=shared.get()+"lets add something";
// Compare and set
success=shared.compareAndSet(prevValue,newValue);
}
Now why is this better? Honestly that code is a little less clean than before. But there is something really important that happens under the hood in AtomicRefrence, and that is compare and swap.
It is a single CPU instruction, not an OS call, that makes the switch happen. That is a single instruction on the CPU. And because there are no locks, there is no context switch in the case where the lock gets exercised which saves even more time!
The catch is, for AtomicReferences, this does not use a .equals() call, but instead an == comparison for the expected value. So make sure the expected is the actual object returned from get in the loop.
14
Your two examples behave differently. You'd have to loop onworked
to get the same semantics.
– CurtainDog
Oct 13 '14 at 20:32
4
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
6
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
@CurtainDog Loop to hope thatshared
might becomeprevValue
again? Good luck :)
– Ivan Balashov
Jul 14 '16 at 6:52
2
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
|
show 1 more comment
An atomic reference is ideal to use when you need to share and change the state of an immutable object between multiple threads. That is a super dense statement so I will break it down a bit.
First, an immutable object is an object that is effectively not changed after construction. Frequently an immutable object's methods return new instances of that same class. Some examples include the wrapper classes of Long and Double, as well as String, just to name a few. (According to Programming Concurrency on the JVM immutable objects are a critical part of modern concurrency).
Next, why AtomicReference is better than a volatile object for sharing that shared value. A simple code example will show the difference.
volatile String sharedValue;
static final Object lock=new Object();
void modifyString(){
synchronized(lock){
sharedValue=sharedValue+"something to add";
}
}
Every time you want to modify the string referenced by that volatile field based on its current value, you first need to obtain a lock on that object. This prevents some other thread from coming in during the meantime and changing the value in the middle of the new string concatenation. Then when your thread resumes, you clobber the work of the other thread. But honestly that code will work, it looks clean, and it would make most people happy.
Slight problem. It is slow. Especially if there is a lot of contention of that lock Object. Thats because most locks require an OS system call, and your thread will block and be context switched out of the CPU to make way for other processes.
The other option is to use an AtomicRefrence.
public static AtomicReference<String> shared = new AtomicReference<>();
String init="Inital Value";
shared.set(init);
//now we will modify that value
boolean success=false;
while(!success){
String prevValue=shared.get();
// do all the work you need to
String newValue=shared.get()+"lets add something";
// Compare and set
success=shared.compareAndSet(prevValue,newValue);
}
Now why is this better? Honestly that code is a little less clean than before. But there is something really important that happens under the hood in AtomicRefrence, and that is compare and swap.
It is a single CPU instruction, not an OS call, that makes the switch happen. That is a single instruction on the CPU. And because there are no locks, there is no context switch in the case where the lock gets exercised which saves even more time!
The catch is, for AtomicReferences, this does not use a .equals() call, but instead an == comparison for the expected value. So make sure the expected is the actual object returned from get in the loop.
An atomic reference is ideal to use when you need to share and change the state of an immutable object between multiple threads. That is a super dense statement so I will break it down a bit.
First, an immutable object is an object that is effectively not changed after construction. Frequently an immutable object's methods return new instances of that same class. Some examples include the wrapper classes of Long and Double, as well as String, just to name a few. (According to Programming Concurrency on the JVM immutable objects are a critical part of modern concurrency).
Next, why AtomicReference is better than a volatile object for sharing that shared value. A simple code example will show the difference.
volatile String sharedValue;
static final Object lock=new Object();
void modifyString(){
synchronized(lock){
sharedValue=sharedValue+"something to add";
}
}
Every time you want to modify the string referenced by that volatile field based on its current value, you first need to obtain a lock on that object. This prevents some other thread from coming in during the meantime and changing the value in the middle of the new string concatenation. Then when your thread resumes, you clobber the work of the other thread. But honestly that code will work, it looks clean, and it would make most people happy.
Slight problem. It is slow. Especially if there is a lot of contention of that lock Object. Thats because most locks require an OS system call, and your thread will block and be context switched out of the CPU to make way for other processes.
The other option is to use an AtomicRefrence.
public static AtomicReference<String> shared = new AtomicReference<>();
String init="Inital Value";
shared.set(init);
//now we will modify that value
boolean success=false;
while(!success){
String prevValue=shared.get();
// do all the work you need to
String newValue=shared.get()+"lets add something";
// Compare and set
success=shared.compareAndSet(prevValue,newValue);
}
Now why is this better? Honestly that code is a little less clean than before. But there is something really important that happens under the hood in AtomicRefrence, and that is compare and swap.
It is a single CPU instruction, not an OS call, that makes the switch happen. That is a single instruction on the CPU. And because there are no locks, there is no context switch in the case where the lock gets exercised which saves even more time!
The catch is, for AtomicReferences, this does not use a .equals() call, but instead an == comparison for the expected value. So make sure the expected is the actual object returned from get in the loop.
edited Jul 17 '16 at 13:29
answered Jul 15 '14 at 18:15
Erik HellerenErik Helleren
84177
84177
14
Your two examples behave differently. You'd have to loop onworked
to get the same semantics.
– CurtainDog
Oct 13 '14 at 20:32
4
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
6
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
@CurtainDog Loop to hope thatshared
might becomeprevValue
again? Good luck :)
– Ivan Balashov
Jul 14 '16 at 6:52
2
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
|
show 1 more comment
14
Your two examples behave differently. You'd have to loop onworked
to get the same semantics.
– CurtainDog
Oct 13 '14 at 20:32
4
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
6
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
@CurtainDog Loop to hope thatshared
might becomeprevValue
again? Good luck :)
– Ivan Balashov
Jul 14 '16 at 6:52
2
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
14
14
Your two examples behave differently. You'd have to loop on
worked
to get the same semantics.– CurtainDog
Oct 13 '14 at 20:32
Your two examples behave differently. You'd have to loop on
worked
to get the same semantics.– CurtainDog
Oct 13 '14 at 20:32
4
4
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
I think you should initialize the value inside the AtomicReference constructor, otherwise another thread may still see the value null before you call shared.set. (Unless shared.set is run in a static initializer.)
– Henno Vermeulen
May 20 '15 at 9:35
6
6
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
In your second example, you should as of Java 8 use something like: shared.updateAndGet( (x) -> (x+"lets add something")); ... which will repeatedly call the .compareAndSet until it works. That is equivalent to the synchronized block which would always succeed. You need to ensure that the lambda you pass in is side-effect-free though because it may be called multiple times.
– Tom Dibble
Dec 9 '15 at 17:02
@CurtainDog Loop to hope that
shared
might become prevValue
again? Good luck :)– Ivan Balashov
Jul 14 '16 at 6:52
@CurtainDog Loop to hope that
shared
might become prevValue
again? Good luck :)– Ivan Balashov
Jul 14 '16 at 6:52
2
2
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
There is not need to make volatile String sharedValue. The synchronized(lock) is good enough to establish the happen before the relationship.
– Jai Pandit
Jul 20 '17 at 5:26
|
show 1 more comment
Here is a use case for AtomicReference:
Consider this class that acts as a number range, and uses individual AtmomicInteger variables to maintain lower and upper number bounds.
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
// Warning -- unsafe check-then-act
if (i > upper.get())
throw new IllegalArgumentException(
"can't set lower to " + i + " > upper");
lower.set(i);
}
public void setUpper(int i) {
// Warning -- unsafe check-then-act
if (i < lower.get())
throw new IllegalArgumentException(
"can't set upper to " + i + " < lower");
upper.set(i);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
}
Both setLower and setUpper are check-then-act sequences, but they do not use sufficient locking to make them atomic. If the number range holds (0, 10), and one thread calls setLower(5) while another thread calls setUpper(4), with some unlucky timing both will pass the checks in the setters and both modifications will be applied. The result is that the range now holds (5, 4)an invalid state. So while the underlying AtomicIntegers are thread-safe, the composite class is not. This can be fixed by using a AtomicReference instead of using individual AtomicIntegers for upper and lower bounds.
public class CasNumberRange {
//Immutable
private static class IntPair {
final int lower; // Invariant: lower <= upper
final int upper;
...
}
private final AtomicReference<IntPair> values =
new AtomicReference<IntPair>(new IntPair(0, 0));
public int getLower() { return values.get().lower; }
public int getUpper() { return values.get().upper; }
public void setLower(int i) {
while (true) {
IntPair oldv = values.get();
if (i > oldv.upper)
throw new IllegalArgumentException(
"Can't set lower to " + i + " > upper");
IntPair newv = new IntPair(i, oldv.upper);
if (values.compareAndSet(oldv, newv))
return;
}
}
// similarly for setUpper
}
1
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
add a comment |
Here is a use case for AtomicReference:
Consider this class that acts as a number range, and uses individual AtmomicInteger variables to maintain lower and upper number bounds.
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
// Warning -- unsafe check-then-act
if (i > upper.get())
throw new IllegalArgumentException(
"can't set lower to " + i + " > upper");
lower.set(i);
}
public void setUpper(int i) {
// Warning -- unsafe check-then-act
if (i < lower.get())
throw new IllegalArgumentException(
"can't set upper to " + i + " < lower");
upper.set(i);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
}
Both setLower and setUpper are check-then-act sequences, but they do not use sufficient locking to make them atomic. If the number range holds (0, 10), and one thread calls setLower(5) while another thread calls setUpper(4), with some unlucky timing both will pass the checks in the setters and both modifications will be applied. The result is that the range now holds (5, 4)an invalid state. So while the underlying AtomicIntegers are thread-safe, the composite class is not. This can be fixed by using a AtomicReference instead of using individual AtomicIntegers for upper and lower bounds.
public class CasNumberRange {
//Immutable
private static class IntPair {
final int lower; // Invariant: lower <= upper
final int upper;
...
}
private final AtomicReference<IntPair> values =
new AtomicReference<IntPair>(new IntPair(0, 0));
public int getLower() { return values.get().lower; }
public int getUpper() { return values.get().upper; }
public void setLower(int i) {
while (true) {
IntPair oldv = values.get();
if (i > oldv.upper)
throw new IllegalArgumentException(
"Can't set lower to " + i + " > upper");
IntPair newv = new IntPair(i, oldv.upper);
if (values.compareAndSet(oldv, newv))
return;
}
}
// similarly for setUpper
}
1
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
add a comment |
Here is a use case for AtomicReference:
Consider this class that acts as a number range, and uses individual AtmomicInteger variables to maintain lower and upper number bounds.
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
// Warning -- unsafe check-then-act
if (i > upper.get())
throw new IllegalArgumentException(
"can't set lower to " + i + " > upper");
lower.set(i);
}
public void setUpper(int i) {
// Warning -- unsafe check-then-act
if (i < lower.get())
throw new IllegalArgumentException(
"can't set upper to " + i + " < lower");
upper.set(i);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
}
Both setLower and setUpper are check-then-act sequences, but they do not use sufficient locking to make them atomic. If the number range holds (0, 10), and one thread calls setLower(5) while another thread calls setUpper(4), with some unlucky timing both will pass the checks in the setters and both modifications will be applied. The result is that the range now holds (5, 4)an invalid state. So while the underlying AtomicIntegers are thread-safe, the composite class is not. This can be fixed by using a AtomicReference instead of using individual AtomicIntegers for upper and lower bounds.
public class CasNumberRange {
//Immutable
private static class IntPair {
final int lower; // Invariant: lower <= upper
final int upper;
...
}
private final AtomicReference<IntPair> values =
new AtomicReference<IntPair>(new IntPair(0, 0));
public int getLower() { return values.get().lower; }
public int getUpper() { return values.get().upper; }
public void setLower(int i) {
while (true) {
IntPair oldv = values.get();
if (i > oldv.upper)
throw new IllegalArgumentException(
"Can't set lower to " + i + " > upper");
IntPair newv = new IntPair(i, oldv.upper);
if (values.compareAndSet(oldv, newv))
return;
}
}
// similarly for setUpper
}
Here is a use case for AtomicReference:
Consider this class that acts as a number range, and uses individual AtmomicInteger variables to maintain lower and upper number bounds.
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
// Warning -- unsafe check-then-act
if (i > upper.get())
throw new IllegalArgumentException(
"can't set lower to " + i + " > upper");
lower.set(i);
}
public void setUpper(int i) {
// Warning -- unsafe check-then-act
if (i < lower.get())
throw new IllegalArgumentException(
"can't set upper to " + i + " < lower");
upper.set(i);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
}
Both setLower and setUpper are check-then-act sequences, but they do not use sufficient locking to make them atomic. If the number range holds (0, 10), and one thread calls setLower(5) while another thread calls setUpper(4), with some unlucky timing both will pass the checks in the setters and both modifications will be applied. The result is that the range now holds (5, 4)an invalid state. So while the underlying AtomicIntegers are thread-safe, the composite class is not. This can be fixed by using a AtomicReference instead of using individual AtomicIntegers for upper and lower bounds.
public class CasNumberRange {
//Immutable
private static class IntPair {
final int lower; // Invariant: lower <= upper
final int upper;
...
}
private final AtomicReference<IntPair> values =
new AtomicReference<IntPair>(new IntPair(0, 0));
public int getLower() { return values.get().lower; }
public int getUpper() { return values.get().upper; }
public void setLower(int i) {
while (true) {
IntPair oldv = values.get();
if (i > oldv.upper)
throw new IllegalArgumentException(
"Can't set lower to " + i + " > upper");
IntPair newv = new IntPair(i, oldv.upper);
if (values.compareAndSet(oldv, newv))
return;
}
}
// similarly for setUpper
}
answered May 29 '15 at 10:00
Binita BharatiBinita Bharati
1,4991614
1,4991614
1
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
add a comment |
1
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
1
1
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
This article is similar to your answer, but goes deep to more complicated things. It's interesting! ibm.com/developerworks/java/library/j-jtp04186
– LppEdd
Oct 8 '18 at 17:32
add a comment |
You can use AtomicReference when applying optimistic locks. You have a shared object and you want to change it from more than 1 thread.
- You can create a copy of the shared object
- Modify the shared object
- You need to check that the shared object is still the same as before - if yes, then update with the reference of the modified copy.
As other thread might have modified it and/can modify between these 2 steps. You need to do it in an atomic operation. this is where AtomicReference can help
add a comment |
You can use AtomicReference when applying optimistic locks. You have a shared object and you want to change it from more than 1 thread.
- You can create a copy of the shared object
- Modify the shared object
- You need to check that the shared object is still the same as before - if yes, then update with the reference of the modified copy.
As other thread might have modified it and/can modify between these 2 steps. You need to do it in an atomic operation. this is where AtomicReference can help
add a comment |
You can use AtomicReference when applying optimistic locks. You have a shared object and you want to change it from more than 1 thread.
- You can create a copy of the shared object
- Modify the shared object
- You need to check that the shared object is still the same as before - if yes, then update with the reference of the modified copy.
As other thread might have modified it and/can modify between these 2 steps. You need to do it in an atomic operation. this is where AtomicReference can help
You can use AtomicReference when applying optimistic locks. You have a shared object and you want to change it from more than 1 thread.
- You can create a copy of the shared object
- Modify the shared object
- You need to check that the shared object is still the same as before - if yes, then update with the reference of the modified copy.
As other thread might have modified it and/can modify between these 2 steps. You need to do it in an atomic operation. this is where AtomicReference can help
answered Jun 12 '15 at 12:30
HamoriZHamoriZ
1,5411129
1,5411129
add a comment |
add a comment |
Here's a very simple use case and has nothing to do with thread safety.
To share an object between lambda invocations, the AtomicReference
is an option:
public void doSomethingUsingLambdas() {
AtomicReference<YourObject> yourObjectRef = new AtomicReference<>();
soSomethingThatTakesALambda(() -> {
yourObjectRef.set(youObject);
});
soSomethingElseThatTakesALambda(() -> {
YourObject yourObject = yourObjectRef.get();
});
}
I'm not saying this is good design or anything (it's just a trivial example), but if you have have the case where you need to share an object between lambda invocations, the AtomicReference
is an option.
In fact you can use any object that holds a reference, even a Collection that has only one item. However, the AtomicReference is a perfect fit.
add a comment |
Here's a very simple use case and has nothing to do with thread safety.
To share an object between lambda invocations, the AtomicReference
is an option:
public void doSomethingUsingLambdas() {
AtomicReference<YourObject> yourObjectRef = new AtomicReference<>();
soSomethingThatTakesALambda(() -> {
yourObjectRef.set(youObject);
});
soSomethingElseThatTakesALambda(() -> {
YourObject yourObject = yourObjectRef.get();
});
}
I'm not saying this is good design or anything (it's just a trivial example), but if you have have the case where you need to share an object between lambda invocations, the AtomicReference
is an option.
In fact you can use any object that holds a reference, even a Collection that has only one item. However, the AtomicReference is a perfect fit.
add a comment |
Here's a very simple use case and has nothing to do with thread safety.
To share an object between lambda invocations, the AtomicReference
is an option:
public void doSomethingUsingLambdas() {
AtomicReference<YourObject> yourObjectRef = new AtomicReference<>();
soSomethingThatTakesALambda(() -> {
yourObjectRef.set(youObject);
});
soSomethingElseThatTakesALambda(() -> {
YourObject yourObject = yourObjectRef.get();
});
}
I'm not saying this is good design or anything (it's just a trivial example), but if you have have the case where you need to share an object between lambda invocations, the AtomicReference
is an option.
In fact you can use any object that holds a reference, even a Collection that has only one item. However, the AtomicReference is a perfect fit.
Here's a very simple use case and has nothing to do with thread safety.
To share an object between lambda invocations, the AtomicReference
is an option:
public void doSomethingUsingLambdas() {
AtomicReference<YourObject> yourObjectRef = new AtomicReference<>();
soSomethingThatTakesALambda(() -> {
yourObjectRef.set(youObject);
});
soSomethingElseThatTakesALambda(() -> {
YourObject yourObject = yourObjectRef.get();
});
}
I'm not saying this is good design or anything (it's just a trivial example), but if you have have the case where you need to share an object between lambda invocations, the AtomicReference
is an option.
In fact you can use any object that holds a reference, even a Collection that has only one item. However, the AtomicReference is a perfect fit.
answered Apr 23 '18 at 9:00
Benny BottemaBenny Bottema
5,14284668
5,14284668
add a comment |
add a comment |
I won't talk much. Already my respected fellow friends have given their valuable input. The full fledged running code at the last of this blog should remove any confusion. It's about a movie seat booking small program in multi-threaded scenario.
Some important elementary facts are as follows.
1> Different threads can only contend for instance and static member variables in the heap space.
2> Volatile read or write are completely atomic and serialized/happens before and only done from memory. By saying this I mean that any read will follow the previous write in memory. And any write will follow the previous read from memory. So any thread working with a volatile will always see the most up-to-date value.
AtomicReference uses this property of volatile.
Following are some of the source code of AtomicReference.
AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between.
As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the full running code.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Solution {
static List<AtomicReference<Integer>> seats;// Movie seats numbered as per
// list index
public static void main(String args) throws InterruptedException {
// TODO Auto-generated method stub
seats = new ArrayList<>();
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
for (Thread t : ths) {
t.join();
}
for (AtomicReference<Integer> seat : seats) {
System.out.print(" " + seat.get());
}
}
/**
* id is the id of the user
*
* @author sankbane
*
*/
static class MyTh extends Thread {// each thread is a user
static AtomicInteger full = new AtomicInteger(0);
List<AtomicReference<Integer>> l;//seats
int id;//id of the users
int seats;
public MyTh(List<AtomicReference<Integer>> list, int userId) {
l = list;
this.id = userId;
seats = list.size();
}
@Override
public void run() {
boolean reserved = false;
try {
while (!reserved && full.get() < seats) {
Thread.sleep(50);
int r = ThreadLocalRandom.current().nextInt(0, seats);// excludes
// seats
//
AtomicReference<Integer> el = l.get(r);
reserved = el.compareAndSet(null, id);// null means no user
// has reserved this
// seat
if (reserved)
full.getAndIncrement();
}
if (!reserved && full.get() == seats)
System.out.println("user " + id + " did not get a seat");
} catch (InterruptedException ie) {
// log it
}
}
}
}
add a comment |
I won't talk much. Already my respected fellow friends have given their valuable input. The full fledged running code at the last of this blog should remove any confusion. It's about a movie seat booking small program in multi-threaded scenario.
Some important elementary facts are as follows.
1> Different threads can only contend for instance and static member variables in the heap space.
2> Volatile read or write are completely atomic and serialized/happens before and only done from memory. By saying this I mean that any read will follow the previous write in memory. And any write will follow the previous read from memory. So any thread working with a volatile will always see the most up-to-date value.
AtomicReference uses this property of volatile.
Following are some of the source code of AtomicReference.
AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between.
As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the full running code.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Solution {
static List<AtomicReference<Integer>> seats;// Movie seats numbered as per
// list index
public static void main(String args) throws InterruptedException {
// TODO Auto-generated method stub
seats = new ArrayList<>();
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
for (Thread t : ths) {
t.join();
}
for (AtomicReference<Integer> seat : seats) {
System.out.print(" " + seat.get());
}
}
/**
* id is the id of the user
*
* @author sankbane
*
*/
static class MyTh extends Thread {// each thread is a user
static AtomicInteger full = new AtomicInteger(0);
List<AtomicReference<Integer>> l;//seats
int id;//id of the users
int seats;
public MyTh(List<AtomicReference<Integer>> list, int userId) {
l = list;
this.id = userId;
seats = list.size();
}
@Override
public void run() {
boolean reserved = false;
try {
while (!reserved && full.get() < seats) {
Thread.sleep(50);
int r = ThreadLocalRandom.current().nextInt(0, seats);// excludes
// seats
//
AtomicReference<Integer> el = l.get(r);
reserved = el.compareAndSet(null, id);// null means no user
// has reserved this
// seat
if (reserved)
full.getAndIncrement();
}
if (!reserved && full.get() == seats)
System.out.println("user " + id + " did not get a seat");
} catch (InterruptedException ie) {
// log it
}
}
}
}
add a comment |
I won't talk much. Already my respected fellow friends have given their valuable input. The full fledged running code at the last of this blog should remove any confusion. It's about a movie seat booking small program in multi-threaded scenario.
Some important elementary facts are as follows.
1> Different threads can only contend for instance and static member variables in the heap space.
2> Volatile read or write are completely atomic and serialized/happens before and only done from memory. By saying this I mean that any read will follow the previous write in memory. And any write will follow the previous read from memory. So any thread working with a volatile will always see the most up-to-date value.
AtomicReference uses this property of volatile.
Following are some of the source code of AtomicReference.
AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between.
As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the full running code.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Solution {
static List<AtomicReference<Integer>> seats;// Movie seats numbered as per
// list index
public static void main(String args) throws InterruptedException {
// TODO Auto-generated method stub
seats = new ArrayList<>();
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
for (Thread t : ths) {
t.join();
}
for (AtomicReference<Integer> seat : seats) {
System.out.print(" " + seat.get());
}
}
/**
* id is the id of the user
*
* @author sankbane
*
*/
static class MyTh extends Thread {// each thread is a user
static AtomicInteger full = new AtomicInteger(0);
List<AtomicReference<Integer>> l;//seats
int id;//id of the users
int seats;
public MyTh(List<AtomicReference<Integer>> list, int userId) {
l = list;
this.id = userId;
seats = list.size();
}
@Override
public void run() {
boolean reserved = false;
try {
while (!reserved && full.get() < seats) {
Thread.sleep(50);
int r = ThreadLocalRandom.current().nextInt(0, seats);// excludes
// seats
//
AtomicReference<Integer> el = l.get(r);
reserved = el.compareAndSet(null, id);// null means no user
// has reserved this
// seat
if (reserved)
full.getAndIncrement();
}
if (!reserved && full.get() == seats)
System.out.println("user " + id + " did not get a seat");
} catch (InterruptedException ie) {
// log it
}
}
}
}
I won't talk much. Already my respected fellow friends have given their valuable input. The full fledged running code at the last of this blog should remove any confusion. It's about a movie seat booking small program in multi-threaded scenario.
Some important elementary facts are as follows.
1> Different threads can only contend for instance and static member variables in the heap space.
2> Volatile read or write are completely atomic and serialized/happens before and only done from memory. By saying this I mean that any read will follow the previous write in memory. And any write will follow the previous read from memory. So any thread working with a volatile will always see the most up-to-date value.
AtomicReference uses this property of volatile.
Following are some of the source code of AtomicReference.
AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between.
As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the full running code.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Solution {
static List<AtomicReference<Integer>> seats;// Movie seats numbered as per
// list index
public static void main(String args) throws InterruptedException {
// TODO Auto-generated method stub
seats = new ArrayList<>();
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
for (Thread t : ths) {
t.join();
}
for (AtomicReference<Integer> seat : seats) {
System.out.print(" " + seat.get());
}
}
/**
* id is the id of the user
*
* @author sankbane
*
*/
static class MyTh extends Thread {// each thread is a user
static AtomicInteger full = new AtomicInteger(0);
List<AtomicReference<Integer>> l;//seats
int id;//id of the users
int seats;
public MyTh(List<AtomicReference<Integer>> list, int userId) {
l = list;
this.id = userId;
seats = list.size();
}
@Override
public void run() {
boolean reserved = false;
try {
while (!reserved && full.get() < seats) {
Thread.sleep(50);
int r = ThreadLocalRandom.current().nextInt(0, seats);// excludes
// seats
//
AtomicReference<Integer> el = l.get(r);
reserved = el.compareAndSet(null, id);// null means no user
// has reserved this
// seat
if (reserved)
full.getAndIncrement();
}
if (!reserved && full.get() == seats)
System.out.println("user " + id + " did not get a seat");
} catch (InterruptedException ie) {
// log it
}
}
}
}
edited May 31 '18 at 6:41
answered May 31 '18 at 5:54


sankar banerjeesankar banerjee
413
413
add a comment |
add a comment |
When do we use AtomicReference?
AtomicReference is flexible way to update the variable value atomically without use of synchronization.
AtomicReference
support lock-free thread-safe programming on single variables.
There are multiple ways of achieving Thread safety with high level concurrent API. Atomic variables is one of the multiple options.
Lock
objects support locking idioms that simplify many concurrent applications.
Executors
define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
Provide a simple example where AtomicReference should be used.
Sample code with AtomicReference
:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
Is it needed to create objects in all multithreaded programs?
You don't have to use AtomicReference
in all multi threaded programs.
If you want to guard a single variable, use AtomicReference
. If you want to guard a code block, use other constructs like Lock
/synchronized
etc.
add a comment |
When do we use AtomicReference?
AtomicReference is flexible way to update the variable value atomically without use of synchronization.
AtomicReference
support lock-free thread-safe programming on single variables.
There are multiple ways of achieving Thread safety with high level concurrent API. Atomic variables is one of the multiple options.
Lock
objects support locking idioms that simplify many concurrent applications.
Executors
define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
Provide a simple example where AtomicReference should be used.
Sample code with AtomicReference
:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
Is it needed to create objects in all multithreaded programs?
You don't have to use AtomicReference
in all multi threaded programs.
If you want to guard a single variable, use AtomicReference
. If you want to guard a code block, use other constructs like Lock
/synchronized
etc.
add a comment |
When do we use AtomicReference?
AtomicReference is flexible way to update the variable value atomically without use of synchronization.
AtomicReference
support lock-free thread-safe programming on single variables.
There are multiple ways of achieving Thread safety with high level concurrent API. Atomic variables is one of the multiple options.
Lock
objects support locking idioms that simplify many concurrent applications.
Executors
define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
Provide a simple example where AtomicReference should be used.
Sample code with AtomicReference
:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
Is it needed to create objects in all multithreaded programs?
You don't have to use AtomicReference
in all multi threaded programs.
If you want to guard a single variable, use AtomicReference
. If you want to guard a code block, use other constructs like Lock
/synchronized
etc.
When do we use AtomicReference?
AtomicReference is flexible way to update the variable value atomically without use of synchronization.
AtomicReference
support lock-free thread-safe programming on single variables.
There are multiple ways of achieving Thread safety with high level concurrent API. Atomic variables is one of the multiple options.
Lock
objects support locking idioms that simplify many concurrent applications.
Executors
define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
Provide a simple example where AtomicReference should be used.
Sample code with AtomicReference
:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
Is it needed to create objects in all multithreaded programs?
You don't have to use AtomicReference
in all multi threaded programs.
If you want to guard a single variable, use AtomicReference
. If you want to guard a code block, use other constructs like Lock
/synchronized
etc.
edited Jan 7 '18 at 7:40
answered May 20 '16 at 6:05


Ravindra babuRavindra babu
29.7k5161136
29.7k5161136
add a comment |
add a comment |
Another simple example is to do a safe-thread modification in a session object.
public PlayerScore getHighScore() {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
return holder.get();
}
public void updateHighScore(PlayerScore newScore) {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
while (true) {
HighScore old = holder.get();
if (old.score >= newScore.score)
break;
else if (holder.compareAndSet(old, newScore))
break;
}
}
Source: http://www.ibm.com/developerworks/library/j-jtp09238/index.html
add a comment |
Another simple example is to do a safe-thread modification in a session object.
public PlayerScore getHighScore() {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
return holder.get();
}
public void updateHighScore(PlayerScore newScore) {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
while (true) {
HighScore old = holder.get();
if (old.score >= newScore.score)
break;
else if (holder.compareAndSet(old, newScore))
break;
}
}
Source: http://www.ibm.com/developerworks/library/j-jtp09238/index.html
add a comment |
Another simple example is to do a safe-thread modification in a session object.
public PlayerScore getHighScore() {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
return holder.get();
}
public void updateHighScore(PlayerScore newScore) {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
while (true) {
HighScore old = holder.get();
if (old.score >= newScore.score)
break;
else if (holder.compareAndSet(old, newScore))
break;
}
}
Source: http://www.ibm.com/developerworks/library/j-jtp09238/index.html
Another simple example is to do a safe-thread modification in a session object.
public PlayerScore getHighScore() {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
return holder.get();
}
public void updateHighScore(PlayerScore newScore) {
ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<PlayerScore> holder
= (AtomicReference<PlayerScore>) ctx.getAttribute("highScore");
while (true) {
HighScore old = holder.get();
if (old.score >= newScore.score)
break;
else if (holder.compareAndSet(old, newScore))
break;
}
}
Source: http://www.ibm.com/developerworks/library/j-jtp09238/index.html
answered Jul 15 '15 at 13:02
DherikDherik
5,79744374
5,79744374
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f3964211%2fwhen-to-use-atomicreference-in-java%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown