How to Implement Exponential Backoff in Rabbitmq Using AMQP in Node.js
Exponential Backoff in Rabbitmq Please make sure to read first, why we need the…
October 31, 2019
Following constraints are applied:
Some add-on requirements
Some basics around singleton implementation:
Lets look at some naive solutions:
class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
Do you see any issue with above code?
Lets lazy-initialize it
class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return singleton;
}
}
Do you see any issue with above code?
Assume you are working in multi-threaded environment. And, there might be a possibility that more than one thread call getInstance() method at the same time. So, all of them are going to see the instance variable as null. And, each one of them will be calling the constructor, and each will receive a new copy. This is the issue of thread safe.
class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return singleton;
}
}
The most naive thread-safe solution is to make whole getInstance() method as synchronized. Synchronized keyword makes a method thread safe, but with extra overhead. Note: it will take a lock on complete class (static method) unnecessary, which is a costly operation. Whereas, we just need to protect the code where we are checking the instance with null.
Lets optimize it.
class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return singleton;
}
}
Above approach is called as Double Lock. For the very first time, when it is not instantiated. Threads might come at first check (instance == null), all of them will proceed. But, there comes the lock now. So, only one thread can enter the protected block. And, again we are checking for null. And, instantiating only when it is not initialized. After this thread exists the protected block. Other thread will enter. Now, it will not see this as null, so it will not instantiate it. The benefit we are getting from this is for further calls, we will never take lock after the instance is initialized.
Do you see any issue with above code?
Well, when the program is loaded into memory. OS and JVM performs bunch of optimizations. And, it allocates separate memory to each thread in the stack. There might be a possibility (for very small duration of time) that when one thread instantiates the class, it still remains in its private memory (stack). And, then another thread again instantiates (even after double lock, because it still sees it as null).
There is special keyword in java: volatile, which applies to declaration of variables.
It is an instruction to compiler that *Do not make any optimization to this thing, and make only one copy of this in memory, so that it will always reflect fresh state*
Now, take a look at the code.
class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return singleton;
}
}
The singleton class looks OK? Right?
Lets take a look at some advanced optimization. If you have used concept of *reflection* of java, you can still call its constructor. Basically you can access even private things of a class using reflection. So, all constaints goes for a toss?
Lets fix this.
class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {
if (instance != null) {
throw new RuntimeException("Use only getInstance() to get instance!");
}
}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return singleton;
}
}
Note the constructor definition now.
Lets look at some pitfalls of this pattern.
Exponential Backoff in Rabbitmq Please make sure to read first, why we need the…
Understanding Simple Message Workflow First, lets understand a simple workflow…
It is very easy to build a software or app. But, it is trickier to have a good…
Introduction In this post we will see following: How to schedule a job on cron…
Introduction There are some cases, where I need another git repository while…
Introduction In this post, we will see how to fetch multiple credentials and…
Introduction I have an automation script, that I want to run on different…
Introduction I had to write a CICD system for one of our project. I had to…
Introduction Java log4j has many ways to initialize and append the desired…