Double checked locking with neither volatile nor a local variable - java

Before dismissing this, it is possible to implement double checked locking without volatile, see below. I'm suggesting a variation on this, that gets rid of the local variable.
The following is a correct implementation of double checked locking from Shipilev:
public class FinalWrapperFactory {
private FinalWrapper wrapper;
public Singleton get() {
FinalWrapper w = wrapper;
if (w == null) { // check 1
synchronized(this) {
w = wrapper;
if (w == null) { // check2
w = new FinalWrapper(new Singleton());
wrapper = w;
}
}
}
return w.instance;
}
private static class FinalWrapper {
public final Singleton instance;
public FinalWrapper(Singleton instance) {
this.instance = instance;
}
}
}
I wonder if it would be possible to get rid of the local variable w:
public class FinalWrapperFactory {
private FinalWrapper wrapper; //same as example above
public Singleton get() {
if (wrapper == null) { // read 1
synchronized(this) {
if (wrapper == null) { // read 2
wrapper = new FinalWrapper(new Singleton());
return wrapper.instance; // read 3
} else {
return wrapper.instance; // read 4
}
}
} else {
return wrapper.instance; // read 5 (last read). Can this be reordered?
}
}
}
In 17.4.8. Executions and Causality Requirements of the JLS 8 it is written:
Informally, we allow an action to be committed early if we know that
the action can occur without assuming some data race occurs.
The big question here is if the last read (read 5) can be reordered so that we could potentially see a non-null wrapper in read 1 and still see a null in the last read. This should not be allowed to happen in the first invocation of get() by a thread because then the only way for the last read to occur would be because of a data race and the JMM would prohibit the reordering.
In subsequent invocations of get() reordering would be allowed but then it shouldn't matter because wrapper should be visible anyways.

Related

How to use the same hashmap in multiple threads

I have a Hashmap that is created for each "mailer" class and each "agent" class creates a mailer.
My problem is that each of my "agents" creates a "mailer" that in turn creates a new hashmap.
What I'm trying to do is to create one Hashmap that will be used by all the agents(every agent is a thread).
This is the Agent class:
public class Agent implements Runnable {
private int id;
private int n;
private Mailer mailer;
private static int counter;
private List<Integer> received = new ArrayList<Integer>();
#Override
public void run() {
System.out.println("Thread has started");
n = 10;
if (counter < n - 1) {
this.id = ThreadLocalRandom.current().nextInt(0, n + 1);
counter++;
}
Message m = new Message(this.id, this.id);
this.mailer.getMap().put(this.id, new ArrayList<Message>());
System.out.println(this.mailer.getMap());
for (int i = 0; i < n; i++) {
if (i == this.id) {
continue;
}
this.mailer.send(i, m);
}
for (int i = 0; i < n; i++) {
if (i == this.id) {
continue;
}
if (this.mailer.getMap().get(i) == null) {
continue;
} else {
this.received.add(this.mailer.readOne(this.id).getContent());
}
}
System.out.println(this.id + "" + this.received);
}
}
This is the Mailer class :
public class Mailer {
private HashMap<Integer, List<Message>> map = new HashMap<>();
public void send(int receiver, Message m) {
synchronized (map) {
while (this.map.get(receiver) == null) {
this.map.get(receiver);
}
if (this.map.get(receiver) == null) {
} else {
map.get(receiver).add(m);
}
}
}
public Message readOne(int receiver) {
synchronized (map) {
if (this.map.get(receiver) == null) {
return null;
} else if (this.map.get(receiver).size() == 0) {
return null;
} else {
Message m = this.map.get(receiver).get(0);
this.map.get(receiver).remove(0);
return m;
}
}
}
public HashMap<Integer, List<Message>> getMap() {
synchronized (map) {
return map;
}
}
}
I have tried so far :
Creating the mailer object inside the run method in agent.
Going by the idea (based on your own answer to this question) that you made the map static, you've made 2 mistakes.
do not use static
static means there is one map for the entire JVM you run this on. This is not actually a good thing: Now you can't create separate mailers on one JVM in the future, and you've made it hard to test stuff.
You want something else: A way to group a bunch of mailer threads together (these are all mailers for the agent), but a bit more discerning than a simple: "ALL mailers in the ENTIRE system are all the one mailer for the one agent that will ever run".
A trivial way to do this is to pass the map in as argument. Alternatively, have the map be part of the agent, and pass the agent to the mailer constructor, and have the mailer ask the agent for the map every time.
this is not thread safe
Thread safety is a crucial concept to get right, because the failure mode if you get it wrong is extremely annoying: It may or may not work, and the JVM is free to base whether it'll work right this moment or won't work on the phase of the moon or the flip of a coin: The JVM is given room to do whatever it feels like it needs to, in order to have a JVM that can make full use of the CPU's powers regardless of which CPU and operating system your app is running on.
Your code is not thread safe.
In any given moment, if 2 threads are both referring to the same field, you've got a problem: You need to ensure that this is done 'safely', and the compiler nor the runtime will throw errors if you fail to do this, but you will get bizarre behaviour because the JVM is free to give you caches, refuse to synchronize things, make ghosts of data appear, and more.
In this case the fix is near-trivial: Use java.util.concurrent.ConcurrentHashMap instead, that's all you'd have to do to make this safe.
Whenever you're interacting with a field that doesn't have a convenient 'typesafe' type, or you're messing with the field itself (one thread assigns a new value to the field, another reads it - you don't do that here, there is just the one field that always points at the same map, but you're messing with the map) - you need to use synchronized and/or volatile and/or locks from the java.util.concurrent package and in general it gets very complicated. Concurrent programming is hard.
I was able to solve this by changing the mailer to static in the Agent class

Java double checked locking code explanation

I have a code snippet that I don't understand I will highlight the bit that confused me.
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance; // <---------- This bit, why do we assign it here ?
if (r == null) {
synchronized (lock) { // What is the benefit of this lock in here
r = instance; // assuming instance is null which will pass the first if ( r == null, what do we assign it again ?? I don't get the idea of this step at all.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
I have seen https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples but there implementation looks like this, which doesn't have two assignments.
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
if(instance == null){
synchronized (ThreadSafeSingleton.class) {
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
YourObject r = instance; // <---------- This bit, why do we assign it here ?
It is easier to reason about local variables, which you really want here. Also there is overhead in reading volatile variables that may not be merged by the optimiser.
synchronized (lock) { // What is the benefit of this lock in here
This is the lock that prevents multiple threads creating and assigning different instances of YourObject simultaneously.
r = instance; // assuming instance is null which will pass the first if ( r == null, what do we assign it again ?? I don't get the idea of this step at all.
instance may have changed between the first read for the null check and the lock being successfully acquired.
Anyway, don't use double-checked locking - it's very confusing and there's probably better ways.

Call synchronised on a function in java

Is there a way I can call synchronised (or something similar) on a block of code. For example (pseudo code),
public int getA(int id) {
if (flag) {
return synchronized(fetchA(id))
} else {
return fetchA(id)
}
}
public int fetchA(int id) {
if (map.get(id) == null) {
p = generate(id)
map.put(id, p)
return map.get(id)
} else {
return map.get(id)
}
}
In this case I want the function to take a lock on object map if flag is set to true and not take a lock otherwise. I have read that synchronised take locks only on objects. Is there any something else I can use instead of synchronised?
Synchronising on an Object ist exactly the right thing to do. In your case the shared object is the map.
You can do a
synchronized(map) {
return fetchA(id);
}
The locking is some sort of contract: if you access map, then you'll have to lock it. This can be cumbersome and error prone. Hence the better option is to lock and release within the fetchA() method, like
public int fetchA(int id) {
synchronized(map) {
if (map.get(id) == null) {
p = generate(id)
map.put(id, p)
return map.get(id)
} else {
return map.get(id)
}
}
}
This way any other method can simply call fetchA() without being aware of the need of locking.
An alternative is to declare the function synchronized. That way only a single thread at the time can enter the function.
public synchronized int fetchA(int id) { ... }
Having said this, be careful with nested locking. That's a good way to produce deadlocks.
To answer your direct question: just use a synchronized block:
synchronized (something) {
return fetchA(id);
}
But your approach is not great in the first place. For one thing, there is the computeIfAbsent method which does exactly what your fetchA method does:
public int fetchA(int id) {
return map.computeIfAbsent(id, k -> generate(k));
}
For another, it seem that flag is going to be a constant for the instance, since it doesn't make sense to access it in a synchronized way only some of the time.
So, choose a Map implementation based on the flag in the constructor:
if (flag) {
map = new ConcurrentHashMap<>();
} else {
map = new HashMap<>();
}
and then simply don't worry about whether you need to synchronize in your method:
public int getA(int id) {
return map.computeIfAbsent(id, k -> generate(k));
}
You could use ConcurrentHashMap. But it will throw "ConcurrentModificationException" if one thread tries to modify it while another is iterating over it.
For block of code level there are four types you can use
Instance methods
enter code here
Static methods
Code blocks inside instance methods
Code blocks inside static methods
refer this for more info :Code block level synchronization

Boolean not changing in thread

I have a class MPClient and MultiplayerMatch. MultiplayerMatch, in his constructor, creates a MPClient runnable thread.
To avoid data overflow, I have a boolean named "moved" in MultiplayerMatch that changes to true when the player is moving.
In the updateMatch method, if there's any player movement, "moved" changes to true, which allow MPClient to enter an if statment (inside while). This way MPClient only sends data to the server when something changes on the game.
Neverthless, when the flag is true, in MPClient that change is not registed! MPClient still "thinks" moved equals false, even after that flag changed in MultiplayerMatch, and as a consequence, nothing is sent to the server...
After a few tests, I noticed that if I run it in Debug Mode, since I have some breakpoints, that change is registered and everything works great!
Why is the boolean change only "seen" though Debug Mode? Does it have something to do with the app "running speed", since there are breakpoints?
Here's only the important part of the code:
MPClient:
public class MPClient {
static final int TIME_OUT = 5000;
Client client;
MultiPlayMatch match;
public MPClient(String name, int team, MultiPlayMatch match) {
this.match = match;
client = new Client();
client.start();
Network.registerPackets(client);
addListeners();
try {
client.connect(TIME_OUT, "127.0.0.1", Network.PORT);
} catch (IOException e) {
e.printStackTrace();
client.stop();
}
/*this comment is just to show that here is the place where the login information is sent to the server, instead of showing all the code*/
PlayerInfo playerInfo = new PlayerInfo();
Network.UpdatePlayer updatePlayer = new Network.UpdatePlayer();
updatePlayer.name = name;
updatePlayer.team = team;
while(true) {
if(match.moved) { //--> this is the variable that is always false
playerInfo.x = match.getClientPlayerX(team);
playerInfo.y = match.getClientPlayerY(team);
updatePlayer.x = playerInfo.x;
updatePlayer.y = playerInfo.y;
client.sendTCP(updatePlayer);
match.moved = false;
}
}
}
private void addListeners() {
client.addListener(new Listener.ThreadedListener(new Listener() {
#Override
public void received(Connection connection, Object object) {
if(object instanceof Network.UpdatePlayer) {
Network.UpdatePlayer updatePlayer = (Network.UpdatePlayer) object;
match.setPlayerPosition(updatePlayer.x, updatePlayer.y, updatePlayer.name, updatePlayer.team);
}
}
}));
}
}
MultiplayerMatch:
public class MultiPlayMatch extends Match {
public boolean moved;
public MultiPlayMatch(){
super(0);
Random r = new Random();
int aux = r.nextInt(2);
aux = 0;
if(aux == 0){
homeTeam = new Team("Benfica", Team.TeamState.Attacking, w);
visitorTeam = new Team("Porto", Team.TeamState.Defending, w);
} else{
homeTeam = new Team("Benfica", Team.TeamState.Defending, w);
visitorTeam = new Team("Porto", Team.TeamState.Attacking, w);
}
//homeTeam.controlPlayer(0);
numberOfPlayers = 0;
moved = false;
}
#Override
public void updateMatch(float x, float y, Rain rain, float dt) {
homeTeam.updateControlledPlayerOnline(x, y);
rain.update();
w.step(Constants.GAME_SIMULATION_SPEED, 6, 2);
if(x != 0 || y != 0) moved = true; //this is the place the variable is changed, but if it isn't in debug mode, MPClient thinks it's always false
}
public void setPlayerPosition(float x, float y, String name, int team) {
if(team == 0)
homeTeam.changePlayerPosition(x, y, name);
else
visitorTeam.changePlayerPosition(x, y, name);
}
}
volatile
This is because it is reading a cached value of match.moved variable instead of the latest. To avoid this, declare the variable as volatile
public volatile boolean moved;
Read more here
tl;dr
AtomicBoolean is a convenient alternative to volatile.
This class wraps and protects a nested primitive boolean value while ensuring proper visibility.
Instantiate:
public final AtomicBoolean moved = new AtomicBoolean( false ) ;
Getter:
boolean x = moved.get() // Returns current value.
Setter:
moved.set( false ) // Sets a new value.
Get, then set:
boolean x = moved.getAndSet( false ) ; // Retrieves the old value before setting a new value.
AtomicBoolean
The Answer by agamagarwal is correct. You have fallen into the visibility conundrum that occurs when accessing variables across threads. One solution is the use of volatile shown there.
Another solution is the Atomic… classes bundled with Java. In this case, AtomicBoolean.
The Atomic… classes wrap a value, and add thread-safe methods for accessing and setting that value.
I often prefer using the Atomic… classes rather than volatile. One reason for this preference is that it makes quite clear and obvious to the user that we are using a protected resource across threads.
Instantiation:
public class MultiPlayMatch extends Match {
public final AtomicBoolean moved = new AtomicBoolean( false ) ;
…
Notice two things about that instantiation:
final ensures that we do not swap out one AtomicBoolean object for another. Such swapping would put us right back into the variable visibility conundrum we are trying to escape.
The AtomicBoolean object is being instantiated at the same time as this outer object (MultiPlayMatch in your case) is being instantiated. So we have ensured that an instance of AtomicBoolean exists before any access, including any access across threads. If we waited until later (“lazy” loading), then we would be falling back into that variable visibility conundrum we are trying to escape.
Getting the value:
if ( this.match.moved.get() ) { … // Returns the primitive `true` or `false` value wrapped within this `AtomicBoolean` object.
And setting the value:
this.match.moved.set( false ) ;
You may want to get the current value while also setting a value in an immediate thread-safe “atomic” (combined) operation:
boolean oldValue = this.match.moved.getAndSet( false ) ;
To learn all about concurrency in Java, see the book, Java Concurrency in Practice by Brian Goetz, et al.

Atomic compareAndSet but with callback?

I know that AtomicReference has compareAndSet, but I feel like what I want to do is this
private final AtomicReference<Boolean> initialized = new AtomicReference<>( false );
...
atomicRef.compareSetAndDo( false, true, () -> {
// stuff that only happens if false
});
this would probably work too, might be better.
atomicRef.compareAndSet( false, () -> {
// stuff that only happens if false
// if I die still false.
return true;
});
I've noticed there's some new functional constructs but I'm not sure if any of them are what I'm looking for.
Can any of the new constructs do this? if so please provide an example.
update
To attempt to simplify my problem, I'm trying to find a less error prone way to guard code in a "do once for object" or (really) lazy initializer fashion, and I know that some developers on my team find compareAndSet confusing.
guard code in a "do once for object"
how exactly to implement that depends on what you want other threads attempting to execute the same thing in the meantime. if you just let them run past the CAS they may observe things in an intermediate state while the one thread that succeeded does its action.
or (really) lazy initializer fashion
that construct is not thread-safe if you're using it for lazy initializers because the "is initialized" boolean may be set to true by one thread and then execute the block while another thread observes the true-state but reads an empty result.
You can use Atomicreference::updateAndGet if multiple concurrent/repeated initialization attempts are acceptable with one object winning in the end and the others being discarded by GC. The update method should be side-effect-free.
Otherwise you should just use the double checked locking pattern with a variable reference field.
Of course you can always package any of these into a higher order function that returns a Runnable or Supplier which you then assign to a final field.
// == FunctionalUtils.java
/** #param mayRunMultipleTimes must be side-effect-free */
public static <T> Supplier<T> instantiateOne(Supplier<T> mayRunMultipleTimes) {
AtomicReference<T> ref = new AtomicReference<>(null);
return () -> {
T val = ref.get(); // fast-path if already initialized
if(val != null)
return val;
return ref.updateAndGet(v -> v == null ? mayRunMultipleTimes.get() : v)
};
}
// == ClassWithLazyField.java
private final Supplier<Foo> lazyInstanceVal = FunctionalUtils.instantiateOne(() -> new Foo());
public Foo getFoo() {
lazyInstanceVal.get();
}
You can easily encapsulate various custom control-flow and locking patterns this way. Here are two of my own..
compareAndSet returns true if the update was done, and false if the actual value was not equal to the expected value.
So just use
if (ref.compareAndSet(expectedValue, newValue)) {
...
}
That said, I don't really understand your examples, since you're passing true and false to a method taking object references as argument. And your second example doesn't do the same thing as the first one. If the second is what you want, I think what you're after is
ref.getAndUpdate(value -> {
if (value.equals(expectedValue)) {
return someNewValue(value);
}
else {
return value;
}
});
You’re over-complicating things. Just because there are now lambda expression, you don’t need to solve everything with lambdas:
private volatile boolean initialized;
…
if(!initialized) synchronized(this) {
if(!initialized) {
// stuff to be done exactly once
initialized=true;
}
}
The double checked locking might not have a good reputation, but for non-static properties, there are little alternatives.
If you consider multiple threads accessing it concurrently in the uninitialized state and want a guaranty that the action runs only once, and that it has completed, before dependent code is executed, an Atomic… object won’t help you.
There’s only one thread that can successfully perform compareAndSet(false,true), but since failure implies that the flag already has the new value, i.e. is initialized, all other threads will proceed as if the “stuff to be done exactly once” has been done while it might still be running. The alternative would be reading the flag first and conditionally perform the stuff and compareAndSet afterwards, but that allows multiple concurrent executions of “stuff”. This is also what happens with updateAndGet or accumulateAndGet and it’s provided function.
To guaranty exactly one execution before proceeding, threads must get blocked, if the “stuff” is currently executed. The code above does this. Note that once the “stuff” has been done, there will be no locking anymore and the performance characteristics of the volatile read are the same as for the Atomic… read.
The only solution which is simpler in programming, is to use a ConcurrentMap:
private final ConcurrentHashMap<String,Boolean> initialized=new ConcurrentHashMap<>();
…
initialized.computeIfAbsent("dummy", ignore -> {
// stuff to do exactly once
return true;
});
It might look a bit oversized, but it provides exactly the required performance characteristics. It will guard the initial computation using synchronized (or well, an implementation dependent exclusion mechanism) but perform a single read with volatile semantics on subsequent queries.
If you want a more lightweight solution, you may stay with the double checked locking shown at the beginning of this answer…
I know this is old, but I've found there is no perfect way to achieve this, more specifically this:
trying to find a less error prone way to guard code in a "do (anything) once..."
I'll add to this "while respecting a happens before behavior." which is required for instantiating singletons in your case.
IMO The best way to achieve this is by means of a synchronized function:
public<T> T transaction(Function<NonSyncObject, T> transaction) {
synchronized (lock) {
return transaction.apply(nonSyncObject);
}
}
This allows to preform atomic "transactions" on the given object.
Other options are double-check spin-locks:
for (;;) {
T t = atomicT.get();
T newT = new T();
if (atomicT.compareAndSet(t, newT)) return;
}
On this one new T(); will get executed repeatedly until the value is set successfully, so it is not really a "do something once".
This would only work on copy on write transactions, and could help on "instantiating objects once" (which in reality is instantiating many but at the end is referencing the same) by tweaking the code.
The final option is a worst performant version of the first one, but this one is a true happens before AND ONCE (as opposed to the double-check spin-lock):
public void doSomething(Runnable r) {
while (!atomicBoolean.compareAndSet(false, true)) {}
// Do some heavy stuff ONCE
r.run();
atomicBoolean.set(false);
}
The reason why the first one is the better option is that it is doing what this one does, but in a more optimized way.
As a side note, in my projects I've actually used the code below (similar to #the8472's answer), that at the time I thought safe, and it may be:
public T get() {
T res = ref.get();
if (res == null) {
res = builder.get();
if (ref.compareAndSet(null, res))
return res;
else
return ref.get();
} else {
return res;
}
}
The thing about this code is that, as the copy on write loop, this one generates multiple instances, one for each contending thread, but only one is cached, the first one, all the other constructions eventually get GC'd.
Looking at the putIfAbsent method I see the benefit is the skipping of 17 lines of code and then a synchronized body:
/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
if (tabAt(tab, i) == f) {
And then the synchronized body itself is another 34 lines:
synchronized (f) {
if (tabAt(tab, i) == f) {
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) {
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
else if (f instanceof TreeBin) {
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent)
p.val = value;
}
}
}
}
The pro(s) of using a ConcurrentHashMap is that it will undoubtedly work.

Categories

Resources