I'm trying to make my module instance as singleton. Came across this article where it speaks about various method to achieve singleton instance creation and also touches broken double check locking and ways to avoid this using volatile.
After reading more about volatile, it seems the thread will never cache this variable and would always read from main memory for it's computation. If I implement my singleton using volatile keyword will my app get impacted by performance since it reads from main memory always.
Image source
Got the following doubts,
Where will the thread local memory reside? In which layer would they be L1,L2 or L3 cache?
If I implement my singleton using volatile which means that i'm reading from main memory each time - so does this mean that i'm increasing the CPU cycle?
Will my app get performance impact if I use this in UI thread?
Sample volatile implementation,
private static volatile ResourceService resourceInstance;
//lazy Initialiaztion
public static ResourceService getInstance () {
if (resourceInstance == null) { // first check
synchronized(ResourceService.class) {
if (resourceInstance == null) { // double check
// creating instance of ResourceService for only one time
resourceInstance = new ResourceService ();
}
}
}
return resourceInstance;
}
Related
Now, before some zealot quotes Knuth forgetting what he spent his life on - the question has a mostly educational purpose, as I struggle to understand memory barriers.
Lets assume:
public class Var<T> {
private T finalized = null;
private boolean isFinal = false;
private T init;
public Var(T init) { this.init = init; }
public T getFinal() { return finalized; }
public T get() { return init; }
public void set(T val) {
if (isSet)
throw new IllegalStateException();
if (val == null)
throw new NullPointerException(); //null means finalized is uninitialized.
init = val;
}
public void freeze() {
isSet = true;
if (!field.compareAndSet(this, null, init))
throw new IllegalStateException();
}
private static void field =
MethodHandles.lookup().findVarHandle(Var.class, "finalized", Object.class);
}
The idea is that a single thread accesses the object in its initial, mutable state, calling get and set. Afterwards it calls freeze and makes the object available
to other threads, which use only getFinal. I want to guarantee those threads see
the frozen value. I don't care what happens if in the mutable state multiple threads access it - it is considered not thread safe at that stage.
The questions are:
do I need an additional memory barrier in getFinal?
do I need it if T is immutable (contains only final fields)?
if I share a reference to a Var before calling freeze, would a getVolatile in getFinal change things? Lets assume again T is immutable, as otherwise, as I understand, reader threads could see it in an unitialized state.
Memory barriers are not a sane mental model for Java. For Java, you need to understand the Java Memory Model.
What you need to ensure is that you should not have a data race; so there should be some happens-before edge between a write and a read (or another write).
In your case, you need to make sure there is a happens-before edge between the construction and configuration of the MyObject-instance, and reading the MyObject-instance. The simplest approach would be:
class MyObject{int a,int b;}
class MyObjectContainer{
volatile MyObject value;
void set(MyObject value){this.value = value;}
MyObject get(){return value;}
}
MyObject object = new MyObject();
object.setA(10)
object.setB(20)
myObjectContainer.set(object);
And a different thread can then call myObjectContainer.get() safely.
The 'value' needs to be volatile. Otherwise, there would be a data race. This is because volatile generates the happens-before edge (volatile variable rule) required. In combination with the program order rule and the transitivity rule, we get a guaranteed happens-before edge. The above approach is also known under the name 'safe publication'.
The above will only work if the MyObject instance is not modified after it has been written to the myObjectContaier. So it is 'effectively' immutable.
On the X86 a volatile-read is extremely cheap because every load already has acquire-semantics. A volatile-read only restricts compiler optimizations (compiler fence) and is not a CPU memory fence. The burden on the X86 is on the volatile store.
In exceptional cases, the volatile-store can be a performance bottleneck because it effectively stalls the loads till the store buffer has been drained. In those cases, you can play with relaxed memory ordering (so officially they are classified as data races) using either Unsafe or the VarHandle. In your case, an acquire-load and release-store would be the first steps down the rabbit hole. Depending on the situation, even a [StoreStore] fence before an opaque-store and an [LoadLoad] after an opaque-load would be as low as you could possibly get.
Do I need getVolatile memory access semantics if the value is set with setVolatile?
The short answer is yes.
do I need an additional memory barrier in getFinal?
You need memory barrier protection, yes. Just because field. compareAndSet(...) has memory protection around the update doesn't mean that another thread will see the update.
If an instance of Var is shared between threads such that one thread calls set() and another calls get() then init needs to be volatile. If one thread calls freeze and another calls getFinal() then finalized needs to be volatile as well.
do I need it if T is immutable (contains only final fields)?
The T object will not be shared in an inconsistent state if all fields are final but that does not protect the Var object. One thread could set the immutable object T and then another thread could call get and still see the init field as `null.
if I share a reference to a Var before calling freeze, would a getVolatile in getFinal change things?
That doesn't change anything.
I'm looking at some legacy code that's of the form
public class Client {
private final Cache cache;
.....
Client( final Cache cache) {
this.cache = cache;
}
public Value get(Key key) {
synchronized(cache){
return this.cache.get(key);
}
}
public void put(Key k , Value v) {
synchronized(this.cache){
return cache.put(k, v);
}
}
}
}
I've never seen an instance variable that could be modified being used as a lock Object, since typically locks are usually final Object instances or just direct Locks via the Java API.
How does the synchronized key word have any effect in this case? Isnt a new lock created for each instance of the Client object?
Would the usage of the synchronized keyword force the cache to be updated before a get/put operation is applied?
Why would synchronization be necessary before a get? Is it to get the cache to be updated to the latest values assuming another thread applied a put interim.
synchronized provides the same guarantees irrespective of whether it is used on a static variable or an instance variable. i.e., memory visibility and atomicity. In your case, it provides thread safety at instance level for the attribute cache.
So, coming to your questions
You are right. Each instance of Clientwill have its own lock. But this is useful when an instance of Client is shared between multiple clients.
After the execution of the synchronized block, CPU local caches will be flushed into the main memory and this ensures memory visibility for other threads. At the start of execution of the synchronized block, local CPU caches will be invalidated and loaded from the main memory. So yes, synchronized will cause the instance variable cache to have the up to date values. Please see Synchronization for more details.
The reason is the same as 2. i.e., to provide memory visibility.
So I have a non-thread safe API (some vendor software) I'm currently using, and the way we're currently using it is one object per thread. i.e. every thread has:
Foo instance = new Foo();
However, this doesn't appear to work for this particular library. Some non-thread safe bits of it still appear to butt heads, so I'm assuming this library has some static values within it. At a few points where we know that it has issues, we currently are using ReentrantLock to lock the class when need be. I.E.
public class Bar {
protected static final ReentrantLock lock = new ReentrantLock();
public void process() {
Foo instance = new Foo();
boolean locked = false;
try{
if(SomeCondition) {
locked = true;
Bar.lock.lock();
}
*//rest of the processing goes here
} finally {
if(locked){
Bar.lock.unlock();
}
}
}
}
My question is: In such an instance where the class in question is NOT thread safe, even when creating new instances of said class, is it better to use locking, or should I look i be using ThreadLocals instead? Will ThreadLocals even alleviate my actual issue? Does a ThreadLocal version of a class actually force static areas of a class to essentially be non-static?
All a ThreadLocal does is create a lookup where each thread can find its own instance of an object, so that no threads have to share. Conceptually you can think of it as a map keyed by thread id.
Letting each thread use its own objects is a good strategy for some cases, it's called "thread confinement" in the JCIP book. A common example of this is that SimpleDateFormat objects were not designed to be thread-safe and concurrent threads using them generated bad results. Using a ThreadLocal lets each thread use its own DateFormat, see this question for an example.
But if your problem is that the object references static fields, then those static fields exist on the class, not on the instance, so using ThreadLocal doesn't do anything to reduce sharing.
If somehow each of your threads used its own classloader then each would have its own class and the static fields on it would not be shared. Otherwise your locking on the class seems reasonable (though probably not speedy considering all your threads would be contending for the same lock).
The best approach would be working with the vendor to get them to fix their broken code.
ThreadLocal will not solve your problem, ThreadLocal simply store different instance for each thread independently. so in your case if you have shared resource on your 3rd party library level that wouldn't solve the problem.
A simple synchronized monitor will solve the problem, since you want to avoid concurrent access to that library, but be aware of the performance penalty of monitor - only one thread can access the lib concurrently
Just do:
public class Bar {
private static final Object LOCK = new Object();
public void process() {
synchronized(LOCK) {
Foo instance = new Foo();
instance.myMethod();
}
}
Given:
A lazy initialized singleton class implemented with double-check locking pattern with all the relevant volatile and synchronized stuff in getInstance. This singleton launches asynchronous operations via an ExecutorService,
There are seven type of tasks, each one identified by a unique key,
When a task is launched, it is stored in a cached based on ConcurrentHashMap,
When a client ask for a task, if the task in the cache is done, a new one is launched and cached; if it is running, the task is retrieved from the cache and passed to the client.
Here is a excerpt of the code:
private static volatile TaskLauncher instance;
private ExecutorService threadPool;
private ConcurrentHashMap<String, Future<Object>> tasksCache;
private TaskLauncher() {
threadPool = Executors.newFixedThreadPool(7);
tasksCache = new ConcurrentHashMap<String, Future<Object>>();
}
public static TaskLauncher getInstance() {
if (instance == null) {
synchronized (TaskLauncher.class) {
if (instance == null) {
instance = TaskLauncher();
}
}
}
return instance;
}
public Future<Object> getTask(String key) {
Future<Object> expectedTask = tasksCache.get(key);
if (expectedTask == null || expectedTask.isDone()) {
synchronized (tasksCache) {
if (expectedTask == null || expectedTask.isDone()) {
// Make some stuff to create a new task
expectedTask = [...];
threadPool.execute(expectedTask);
taskCache.put(key, expectedTask);
}
}
}
return expectedTask;
}
I got one major question, and another minor one:
Do I need to perform double-check locking control in my getTask method? I know ConcurrentHashMap is thread-safe for read operations, so my get(key) is thread-safe and may not need double-check locking (but yet quite unsure of this…). But what about the isDone() method of Future?
How do you chose the right lock object in a synchronized block? I know it must no be null, so I use first the TaskLauncher.class object in getInstance() and then the tasksCache, already initialized, in the getTask(String key) method. And has this choice any importance in fact?
Do I need to perform double-check locking control in my getTask method?
You don't need to do double-checked locking (DCL) here. (In fact, it is very rare that you need to use DCL. In 99.9% of cases, regular locking is just fine. Regular locking on a modern JVM is fast enough that the performance benefit of DCL is usually too small to make a noticeable difference.)
However, synchronization is necessary unless you declared tasksCache to be final. And if tasksCache is not final, then simple locking should be just fine.
I know ConcurrentHashMap is thread-safe for read operations ...
That's not the issue. The issue is whether reading the value of the taskCache reference is going to give you the right value if the TaskLauncher is created and used on different threads. The thread-safety of fetching a reference from a variable is not affected one way or another by the thread-safety of the referenced object.
But what about the isDone() method of Future?
Again ... that has no bearing on whether or not you need to use DCL or other synchronization.
For the record, the memory semantics "contract" for Future is specified in the javadoc:
"Memory consistency effects: Actions taken by the asynchronous computation happen-before actions following the corresponding Future.get() in another thread."
In other words, no extra synchronization is required when you call get() on a (properly implemented) Future.
How do you chose the right lock object in a synchronized block?
The locking serves to synchronize access to the variables read and written by different threads while hold the lock.
In theory, you could write your entire application to use just one lock. But if you did that, you would get the situation where one thread waits for another, despite the first thread not needing to use the variables that were used by the other one. So normal practice is use a lock that is associated with the variables.
The other thing you need to be ensure is that when two threads need to access the same set of variables, they use the same object (or objects) as locks. If they use different locks, then they don't achieve proper synchronization ...
(There are also issues about whether lock on this or on a private lock, and about the order in which locks should be acquired. But these are beyond the scope of the question you asked.)
Those are the general "rules". To decide in a specific case, you need to understand precisely what you are trying to protect, and choose the lock accordingly.
AbstractQueuedSync used in side FutureTask has a variable state of a
thread and its a volatile (thread safe) variable. So need not to worry about isDone() method.
private volatile int state;
Choice of lock object is based on the instance type and situation,
Lets say you have multiple objects and they have Sync blocks on
TaskLauncher.class then all the methods in all the instances with be
synchronized by this single lock (use this if you want to share a
single shared memory across all the instances).
If all instances have their own shared memory b/w threads and methods use this. Using this will save you one extra lock object as well.
In your case you can use
TaskLauncher.class ,tasksCache, this its all same in terms of synchronization as its singelton.
In a multi-threaded environment, how can a thread possibly see a 'partially constructed object'? I understood that it is not thread-safe since multiple threads can create multiple instances.
class LazyInit
{ private static Resource resource = null;
public static getInstance()
{ if (resource == null) { resource = new Resource(); }
return instance;
}
}
Because of out-of-order writes.
If your constructor writes to non-final members, they don't have to be committed to memory right away, and actually they may even be committed after the singleton variable is. Java guarantees the thread that affects it sees the affectations in order, but not that other threads will unless you put a memory barrier.
See this question and this page of the Java specification for more information.
It might be beside the point but in your example, it is entirely possible that two threads see different singletons. Suppose one thread tests the nullity of the variable, enters the if and gets preempted before it gets a chance to construct the object. The new thread that gets the CPU now tests the yet-null object, constructs the singleton. When the old thread starts running again it will happily finish constructing the object and overwrite the singleton variable.
Another, more frightening issue, arises if the constructor of Resource calls for a method that will ultimately result in another call to this getInstance. Even if the state of the program results in no infinite loop, you will create several singleton instances.