Is "double checked locking" broken here in java? - java

I find an example for double checked locking.
However, I think this example is invalid because it's possible that another thread may see a non-null reference to a DoorControlManage object of door 1 but see the default values for fields of the DoorControlManage object of door 1 rather than the values set in the constructor.
(Ref: https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)
Could you let me know whether I am right?
Thanks a lot!
public class DoorControlManager {
private static HashMap<Integer, DoorControlManager> mInstances = new HashMap<>();
public static DoorControlManager getInstance(int door) {
if (!mInstances.containsKey(door)) {
synchronized (mInstances) {
if (!mInstances.containsKey(door)) {
mInstances.put(slotId, new DoorControlManager(door));
}
}
}
return mInstances.get(slotId);
}
...
}

Yes this code is broken, though not for the normal reason.
In this case, you have different threads accessing HashMap without proper synchronization. Since HashMap is not a thread-safe class, this is not thread-safe. It is possible that the first containsKey call will see stale values the internals of the map, and behave in unspecified (implementation dependent) ways.
Making "simple" changes to concurrency sensitive code can completely destroy the properties that make the original version thread-safe. If you are going to attempt to write "clever" code like this, you need to have a deep understanding of Java concurrency ... and how the Java Memory Model really works.
There are a couple of ways that this code could be written correctly:
Use a ConcurrentHashMap and implement the getInstance method as:
return mInstances.computeIfAbsent(
slotId, () -> new DoorControlManager(door));
Keep using a HashMap and don't use the DCL pattern. Simply lock before testing.
Note that DCL initialization pattern in Java 5+ is not broken, provided that the you are initializing a single field and the field is declared as volatile. But there are other (better) ways to achieve the same effect, so its use is not recommended.

Related

Java store reflected Method statically in class: Safe?

Is something like the following 'safe' in Java, and why?
public final class Utility {
private Utility() {}
private static Method sFooMethod = null;
public static void callFoo(SomeThing thing) {
try {
if(sFooMethod == null)
sFooMethod = SomeThing.class.getMethod("foo");
sFooMethod.invoke(thing);
} catch(Exception e) {} // Just for simplicity here
}
}
My rationale would be that even if another thread writes to sFooMethod in the background and the current thread sees it suddenly somewhere during execution of callFoo(), it would still just result in the same old reflective invoke of thing.foo()?
Extra question: In what ways does the following approach differ (positive/negative) from the above? Would it be preferred?
public final class Utility {
private Utility() {}
private static final Method sFooMethod;
static {
try {
sFooMethod = SomeThing.class.getMethod("foo");
} catch(Exception e) {}
}
public static void callFoo(SomeThing thing) {
try {
if(sFooMethod != null)
sFooMethod.invoke(thing);
} catch(Exception e) {}
}
}
Background update from comment:
I am writing an Android app and I need to call a method that was private until API 29, when it was made public without being changed. In an alpha release (can't use this yet) of the AndroidX core library Google provides a HandlerCompat method that uses reflection to call the private method if it is not public. So I copied Google's method into my own HandlerCompatP class for now, but I noticed that if I call it 1000 times, then the reflective lookup will occur 1000 times (I couldn't see any caching). So that got me thinking about whether there is a good way to perform the reflection once only, and only if needed.
"Don't use reflection" is not an answer here as in this case it is required, and Google themselves intended for it to happen in their compatibility library. My question is also not whether using reflection is safe and/or good practice, I'm well aware it's not good in general, but instead whether given that I am using reflection, which method would be safe/better.
The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.
Java language specification states following:
17.4.5. Happens-before Order
Two actions can be ordered by a happens-before relationship. If one
action happens-before another, then the first is visible to and
ordered before the second.
If we have two actions x and y, we write hb(x, y) to indicate that x
happens-before y.
If x and y are actions of the same thread and x comes before y in
program order, then hb(x, y).
As, in your case, writing to and then reading from the static field are happening in same tread. So the `happens before' relation is established. So the read operation will always see effects of the write operation.
Also, all threads are going to write same data. At worse, all eligible threads will write to the variable same time. The variable will have reference to the object that got assigned last and rest of the dereferenced objects will be garbage collected.
There won't be many threads in your App which will enter the same method at once, which will cause significant performance hit due to lot of object creation. But if you want to set the variable only once then second approach is better. As static blocks are thread safe.
Is something like the following 'safe' in Java, and why?
No I would not recommend using reflections, unless you have to.
Most of the time developers design their classes in a way, so that access to a hidden field or method is never required. There will most likely be a better way to access the hidden content.
Especially hidden fields and methods could change their name, when the library they are contained in is updated. So your code could just stop working suddenly and you would not know why, since the compiler would not output any errors.
It is also faster to directly access a method or field then through reflections, because the reflections first need to search for it and the direct access don't
So don't use reflections if you don't have to
I'm not sure what your goal is -- there is probably a better way to do what you're trying to do.
The second approach, with a static initializer, is preferable because your first implementation has a race condition.

What is wrong in sharing Mutable State? [duplicate]

This question already has answers here:
How shall we write get method, so that private fields don't escape their intended scope? [duplicate]
(2 answers)
Closed 3 years ago.
In Java Concurrency in Practice chapter # 3 author has suggested not to share the mutable state. Further he has added that below code is not a good way to share the states.
class UnsafeStates {
private String[] states = new String[] {
"AK", "AL"
};
public String[] getStates() {
return states;
}
}
From the book:
Publishing states in this way is problematic because any caller can modify its contents. In this case, the states array has escaped its intended scope, because what was supposed to be private state has been effectively made public.
My question here is: we often use getter and setters to access the class level private mutable variables. if it is not the correct way, what is the correct way to share the state? what is the proper way to encapsulate states ?
For primitive types, int, float etc, using a simple getter like this does not allow the caller to set its value:
someObj.getSomeInt() = 10; // error!
However, with an array, you could change its contents from the outside, which might be undesirable depending on the situation:
someObj.getSomeArray()[0] = newValue; // perfectly fine
This could lead to problems where a field is unexpectedly changed by other parts of code, causing hard-to-track bugs.
What you can do instead, is to return a copy of the array:
public String[] getStates() {
return Arrays.copyOf(states, states.length);
}
This way, even the caller changes the contents of the returned array, the array held by the object won't be affected.
With what you have it is possible for someone to change the content of your private array just through the getter itself:
public static void main(String[] args) {
UnsafeStates us = new UnsafeStates();
us.getStates()[0] = "VT";
System.out.println(Arrays.toString(us.getStates());
}
Output:
[VT, AR]
If you want to encapsulate your States and make it so they cannot change then it might be better to make an enum:
public enum SafeStates {
AR,
AL
}
Creating an enum gives a couple advantages. It allows exact vales that people can use. They can't be modified, its easy to test against and can easily do a switch statement on it. The only downfall for going with an enum is that the values have to be known ahead of time. I.E you code for it. Cannot be created at run time.
This question seems to be asked with respect to concurrency in particular.
Firstly, of course, there is the possibility of modifying non-primitive objects obtained via simple-minded getters; as others have pointed out, this is a risk even with single-threaded programs. The way to avoid this is to return a copy of an array, or an unmodifiable instance of a collection: see for example Collections.unmodifiableList.
However, for programs using concurrency, there is risk of returning the actual object (i.e., not a copy) even if the caller of the getter does not attempt to modify the returned object. Because of concurrent execution, the object could change "while he is looking at it", and in general this lack of synchronization could cause the program to malfunction.
It's difficult to turn the original getStates example into a convincing illustration of my point, but imagine a getter that returns a Map instead. Inside the owning object, correct synchronization may be implemented. However, a getTheMap method that returns just a reference to the Map is an invitation for the caller to call Map methods (even if just map.get) without synchronization.
There are basically two options to avoid the problem: (1) return a deep copy; an unmodifiable wrapper will not suffice in this case, and it should be a deep copy otherwise we just have the same problem one layer down, or (2) do not return unmediated references; instead, extend the method repertoire to provide exactly what is supportable, with correct internal synchronization.

Is iterating over a list retrieved in a synchronized block thread-safe?

I am a bit confused regarding one pattern I have seen in some legacy code of ours.
The controller uses a map as a cache, with an approach that should be thread safe, however I am still not confident it indeed is. We have a map, which is properly synchronized during addition and retrieval, however, there is a bit of logic outside of the synchronized block, that does some additional filtering.
(the map itself and the lists are never accessed outside of this method, so concurrent modification is not an issue; the map holds some stable parameters, which basically never change, but are used often).
The code looks like the following sample:
public class FooBarController {
private final Map<String, List<FooBar>> fooBarMap =
new HashMap<String, List<FooBar>>();
public FooBar getFooBar(String key, String foo, String bar) {
List<FooBar> foobarList;
synchronized (fooBarMap) {
if (fooBarMap.get(key) == null) {
foobarList = queryDbByKey(key);
fooBarMap.put(key, foobarList);
} else {
foobarList = fooBarMap.get(key);
}
}
for(FooBar fooBar : foobarList) {
if(foo.equals(fooBar.getFoo()) && bar.equals(fooBar.getBar()))
return fooBar;
}
return null;
}
private List<FooBar> queryDbByKey(String key) {
// ... (simple Hibernate-query)
}
// ...
}
Based on what I know about the JVM memory model, this should be fine, since if one thread populates a list, another one can only retrieve it from the map with proper synchronization in place, ensuring that the entries of the list is visible. (putting the list happens-before getting it)
However, we keep seeing cases, where an entry expected to be in the map is not found, combined with the typical notorious symptoms of concurrency issues (e.g. intermittent failures in production, which I cannot reproduce in my development environment; different threads can properly retrieve the value etc.)
I am wondering if iterating through the elements of the List like this is thread-safe?
The code you provided is correct in terms of concurrency. Here are the guarantees:
only one thread at a time adds values to map, because of synchronization on map object
values added by thread become visible for all other threads, that enter synchronized block
Given that, you can be sure that all threads that iterate a list see the same elements. The issues you described are indeed strange but I doubt they're related to the code you provided.
It could be thread safe only if all access too fooBarMap are synchronized. A little out of scope, but safer may be to use a ConcurrentHashmap.
There is a great article on how hashmaps can be synchronized here.
In situation like this it's best option to use ConcurrentHashMap.
Verify if all Update-Read are in order.
As I understood from your question. There are fix set of params which never changes. One of the ways I preferred in situation like this is:
I. To create the map cache during start up and keep only one instance of it.
II. Read the map Instance anytime anywhere in the application.
In the for loop you are returning reference to fooBar objects in the foobarList.
So the method calling getFooBar() has access to the Map through this fooBar reference object.
try to clone fooBar before returning from getFooBar()

Is the following code thread-safe? [duplicate]

This question already has answers here:
Java double checked locking
(11 answers)
Closed 7 years ago.
The following code uses a double checked pattern to initialize variables. I believe the code is thread safe, as the map wont partially assigned even if two threads are getting into getMap() method at the same time. So I don't have to make the map as volatile as well. Is the reasoning correct? NOTE: The map is immutable once it is initialized.
class A {
private Map<String, Integer> map;
private final Object lock = new Object();
public static Map<String, Integer> prepareMap() {
Map<String, Integer> map = new HashMap<>();
map.put("test", 1);
return map;
}
public Map<String, Integer> getMap() {
if (map == null) {
synchronized (lock) {
if (map == null) {
map = prepareMap();
}
}
}
return map;
}
}
According to the top names in the Java world, no it is not thread safe. You can read why here: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
You better off using ConcurrentHashmap or synchronizing your Map.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html
Edit: If you only want to make the initialization of the map thread safe (so that two or more maps are not accidentally created) then you can do two things. 1) initialize the map when it is declared. 2) make the getMap() method synchronized.
No, your reasoning is wrong, access to the map is not thread safe, because the threads that call getMap() after the initialization may not invoke synchronized(lock) and thus are not in happens-before relation to other threads.
The map has to be volatile.
The code could be optimized by inlining to
public Map<String,Integer> getMap()
{
if(map == null)
{
synchronized(lock)
{
if(map == null)
{
map = new HashMap<>(); // partial map exposed
map.put("test", 1);
}
}
}
return map;
}
}
Having a HashMap under concurrent read and write is VERY dangerous, don't do it. Google HashMap infinite loop.
Solutions -
Expand synchronized to the entire method, so that reading map variable is also under lock. This is a little expensive.
Declare map as volatile, to prevent reordering optimization. This is simple, and pretty cheap.
Use an immutable map. The final fields will also prevent exposing partial object state. In your particular example, we can use Collections.singletonMap. But for maps with more entries, I'm not sure JDK has a public implementation.
This is just one example of how things can go wrong. To fully understand the issues, there is no substitute for reading The "Double-Checked Locking is Broken" Declaration, referenced in a prior answer.
To get anything approaching the full flavor, think about two processors, A and B, each with its own caches, and a main memory that they share.
Suppose Thread A, running on Processor A, first calls getMap. It does several assignments inside the synchronized block. Suppose the assignment to map gets written to main memory first, before Thread A reaches the end of the synchronized block.
Meanwhile, on Processor B, Thread B also calls getMap, and does not happen to have the memory location representing map in its cache. It goes out to main memory to get it, and its read happens to hit just after Thread A's assignment to map, so it sees a non-null map. Thread B does not enter the synchronized block.
At this point, Thread B can go ahead and attempt to use the HashMap, despite the fact that Thread A's work on creating it has not yet been written to main memory. Thread B may even have the memory pointed to by map in its cache because of a prior use.
If you are tempted to try to work around this, consider the following quote from the referenced article:
There are lots of reasons it doesn't work. The first couple of reasons
we'll describe are more obvious. After understanding those, you may be
tempted to try to devise a way to "fix" the double-checked locking
idiom. Your fixes will not work: there are more subtle reasons why
your fix won't work. Understand those reasons, come up with a better
fix, and it still won't work, because there are even more subtle
reasons.
This answer only contains one of the most obvious reasons.
No, it is not thread safe.
The basic reason is that you can have reordering of operations you don't even see in the Java code. Let's imagine a similar pattern with an even simpler class:
class Simple {
int value = 42;
}
In the analogous getSimple() method, you assign /* non-volatile */ simple = new Simple (). What happens here?
the JVM allocates some space for the new object
the JVM sets some bit of this space to 42 (for value)
the JVM returns the address of this space, which is then assigned to space
Without synchronization instructions to prohibit it, these instructions can be reordered. In particular, steps 2 and 3 can be ordered such that simple gets the new object's address before the constructor finishes! If another thread then reads simple.value, it'll see a value 0 (the field's default value) instead of 42. This is called seeing a partially-constructed object. Yes, that's weird; yes, I've seen things like that happen. It's a real bug.
You can imagine how if the object is a non-trivial object, like HashMap, the problem is even worse; there are a lot more operations, and so more possibilities for weird ordering.
Marking the field as volatile is a way of telling the JVM, "any thread that reads a value from this field must also read all operations that happened before that value was written." That prohibits those weird reorderings, which guarantees you'll see the fully-constructed object.
Unless you declare the lock as volatile, this code may be translated to non-thread-safe bytecode.
The compiler may optimize the expression map == null, cache the value of the expression and thus read the map property only once.
volatile Map<> map instructs the Java VM to always read the property map when it is accessed. Thsi would forbid such optimization from the complier.
Please refer to JLS Chapter 17. Threads and Locks

Can you lock on a local object in Java?

I have this snippet of code
private Templates retrieveFromCache(String name) {
TemplatesWrapper t = xlCache.get(name);
synchronized(t){
if (!t.isValid()) {
xlCache.remove(name);
return null;
}
}
return t.getTemplate();
}
xlCache is a ConcurrentHashMap; my reason for synchronizing on t is that 2 threads could interleave where by the time Thread 1 verifies the predicate Thread 2 has already removed the object from the map and then a NullPointerException would be thrown. Is my assumption correct as I know concurrency is one of the more difficult things to reason about. And then to my original question, can I lock on t even if it's local?
And this is private method as well which gets called from a public method, does it make a diff?
EDIT: MY original premise that a NullPointerException is thrown was incorrect as remove() returns boolean making synchronization moot; however, my question was of locking on a local object was answered.
ConcurrentHashMap (and Map/ConcurrentMap in general) won't throw an exception if the specified key doesn't exist. That's why the remove method returns a boolean, to indicate whether or not anything was actually removed.
But yes, you can lock on the local variable. After all, you're really locking via a reference (and the monitor associated with the referenced object), not a variable - and the other concurrently running method would have the same reference.
You can lock on any object you want. However, in your case, it looks like you could solve it in a clearer and safer.
Synchronization should be as localized as possible. Since you're getting the TemplatesWrapper from some unknown location, its possible that anyone can synchronize on it making it really hard to control the concurrency. It should also be as obvious as possible just by looking at the code why something gets locked.
It would be better off to put the synchronization inside xlCache with something like removeIfInvalid()
Yep, that will work just fine.
You can synchronize on any object in java so you code will work and will be thread safe.
Appart from the fact that you aren't checking for t being null. I'm guessing you have just missed that out of your code example?
A better way to do this would be to use the 2 arg remove method from ConcurrentMap (assuming t has a reasonable equals implementation). then you don't need any synchronization:
private Templates retrieveFromCache(String name) {
TemplatesWrapper t = xlCache.get(name);
if (!t.isValid()) {
xlCache.remove(name, t);
return null;
}
return t.getTemplate();
}
If remove(null) would call a null pointer exception, this seems reasonable. If you don't expect collision to be a regular problem, you could also implement a possibly-faster version of the code, by just wrapping a try/catch around that instead of a synchronized.
In either case, I'd add a comment there to explain why you did what you did, so that a month from now, it still makes sense.

Categories