Morgan Stanley Interview Question
Java DevelopersCountry: India
Interview Type: Phone Interview
This was the first answer I gave. But this implementation sucks , as it blocks all requesting threads that need only to fetch object reference. To make it efficient , solution has to be that we can get Singleton object reference anytime , since its a read only meahod.
private static SingletonObject obj;
SingletonObject getReference()
{
if (obj!=null)
return obj;
else
{
synchronized(this)
{
while(obj==null)
{
obj = new SingletonObject();
}
return obj;
}
}}
Singleton is a DP where only a single object of the class can be created.
class Singleton{
private :
Singleton();// Constructor is private
public :
Singleton & getInstance()
{
// Add thread lock here to make it thread safe
if(!object)
object=new Singleton();
// Release Lock
return object;
}
}
static *Singleton object=NULL; // Static Object must in C++ not required in Java
There are various well tested design practices called design pattern that tells how to structure your classes and interfaces to solve a problem which enhances maintainability and extendanbility. ie: Strategy Design patten , Decorator design pattern , Factory design pattern , Iterator and yes my favorate ie most simplest and most frequently asked in tech interview -Singleton Design pattern :It gives you a well tested and accepted method that solves how to instantiate one and only one object for a given class ans gives a global point of access to it without having the downside of global variable in language like C++. Looks simple and mouthful right??:P.
This design patterns is something like:
Algo:
Create a class called Singleton
declare its state and behaviour with one private static volatile Singleton type variable called uniqueInstatnce.
Make constructor as private so that only class can create object.
add private static method(interface to create object) as below:
public static getInstance(){
if(uniqueInstance==NULL){
synchronized(this){
if(uniqueInstance==NULL){
uniqueInstance=new Singleton();
}
}
return uniqueInstance;
}
class Singleton{
private static Singleton instance=null;
private Singleton() { }
synchronize private static void createInstance(){
if(instance==null)
instance=new Singleton();
}
public static Singleton getInstance() {
if(instance==null)
{
createInstance();
}
return instance;
}
}
my 2 cent
package designpattern;
import java.util.concurrent.CountDownLatch;
import com.vikalp.util.LOG;
import designpattern.SingltonExample.MyEnumSingleton;
public class SingltonExample {
//throw exception on clone method
private static volatile SingltonExample instance;
private SingltonExample(){
System.out.println("sfdf dfdf");
}
//In an effort to make this method more efficient, an idiom called double-checked locking was
//created.The idea is to avoid the costly synchronization for all invocations of the method
//except the first. The cost of synchronization differs from JVM to JVM. In the early days,
//the cost could be quite high.As more advanced JVMs have emerged, the cost of synchronization
//has decreased, but there is still a performance penalty for entering and leaving a
//synchronized method or block. Regardless of the advancements in JVM technology, programmers
//never want to waste processing time unnecessarily.
//This can still fail with multi processor
public static SingltonExample getInstance(){
// synchronized only when instance is null so we can save synchronization cost
if(instance == null){
synchronized(SingltonExample.class){ // one one thread can enter here
if(instance == null){
instance = new SingltonExample();
}
}
return instance;
}
else{
return instance;
}
}
void rest(String name) throws InterruptedException{
LOG.debug("Resting the instance---Thred name "+name);
Thread.sleep(1000);
}
public Object clone() throws CloneNotSupportedException {
//throw new CloneNotSupportedException();
return super.clone();
}
public static void main(String[] args){
SingltonExample myCopy = SingltonExample.getInstance();
LOG.debug(myCopy);
CountDownLatch startLatch = new CountDownLatch(1);
for (int i=0;i<50;i++){
new Thread(new client(startLatch," Thread:"+i)).start();
}
startLatch.countDown();
}
//java 1.6 onwards
// package mypackage;
//
public enum MyEnumSingleton {
INSTANCE;
private MyEnumSingleton(){
LOG.debug("-----");
}
void rest(String name) throws InterruptedException{
LOG.debug("Resting the instance---Thred name "+name);
Thread.sleep(1000);
}
// other useful methods here
}
/*
* Another good way
*/
// public class Sing{
// private static instance = new Sing();
// private Singh()
// {
// }
// public static Sing getInstance(){
// return instance;
// }
}
class client implements Runnable{
CountDownLatch latch;
String name;
client(CountDownLatch latch,String name){
this.latch = latch;
this.name = name;
}
@Override
public void run() {
try {
latch.await();
// SingltonExample myCopy = SingltonExample.getInstance();
// LOG.debug(myCopy);
// myCopy.rest(name);
MyEnumSingleton.INSTANCE.rest(name);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
}
}
public class Singleton{
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null){
synchronized(Singleton.class){
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
You can use below approach in C#. Its called Double - locking technique.
public class MySingleton
{
private static MySingleton s_UniqueInstance;
//Any light weight object for locking.
private static readonly Object s_ObjectToLock = new Object();
private MySingleton()
{
}
public static MySingleton UniqueInstance
{
get
{
if (s_UniqueInstance != null)
{
return s_UniqueInstance;
}
lock (s_ObjectToLock)
{
MySingleton tmp = new MySingleton();
if (s_UniqueInstance != null)
{
Volatile.Write(ref s_UniqueInstance, tmp);
}
}
return s_UniqueInstance;
}
}
}
public class EagerSingleton {
private static volatile EagerSingleton instance = null;
// private constructor
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
if (instance == null) {
synchronized (EagerSingleton.class) {
// Double check
if (instance == null) {
instance = new EagerSingleton();
}
}
}
return instance;
}
}
public class EagerSingleton {
private static volatile EagerSingleton instance = null;
// private constructor
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
if (instance == null) {
synchronized (EagerSingleton.class) {
// Double check
if (instance == null) {
instance = new EagerSingleton();
}
}
}
return instance;
}
}
public class EagerSingleton {
private static volatile EagerSingleton instance = null;
// private constructor
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
if (instance == null) {
synchronized (EagerSingleton.class) {
// Double check
if (instance == null) {
instance = new EagerSingleton();
}
}
}
return instance;
}
}
public class EagerSingleton {
private static volatile EagerSingleton instance = null;
// private constructor
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
if (instance == null) {
synchronized (EagerSingleton.class) {
// Double check
if (instance == null) {
instance = new EagerSingleton();
}
}
}
return instance;
}
}
In C++ 11 static initialization is guaranteed thread-safe, so:
class Singleton
{
public:
static Singleton& instance()
{
static Singleton instance; // in C++ 11 standard guaranteed thread-safe without dead-locks
return instance;
}
private:
Singleton()
{
}
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
};
Here is the implementation in java:
- Rage January 28, 2013