http://www.hollischuang.com/archives/1866
不使用synchronized和lock,如何实现一个线程安全的单例?(二)
Java Singleton Design Pattern Best Practices with Examples
Singleton using Enum in Java
public enum EasySingleton{
INSTANCE;
}
Enum Singletons handled Serialization by themselves
Creation of Enum instance is thread-safe
As stated in point 1 since creatino of Enum instance is thread-safe by default you don't need to worry about double checked locking.
Eager initialization
Static block initialization ==> to handle exception during initialization
https://hellosmallworld123.wordpress.com/2014/07/28/singleton-object-design-pattern/
try finally ?
Lazy Initialization
Double-Checked Locking (DCL) idiom
http://stackoverflow.com/questions/1879283/different-ways-to-write-singleton-in-java
the double checked locking helps improve efficiency with the first lock (because it checks if instance is null or not before entering the synchronized block so that if eliminates the overhead of doing checking after the singleton is initialized. While the second check makes sure that creation of the instance is atomic.
nitialization on Demand Holder (IODH) idiom
requires very little code and has zero synchronization overhead. Zero, as in even faster than volatile. IODH requires the same number of lines of code as plain old synchronization, and it's faster than DCL!
IODH utilizes lazy class initialization. The JVM won't execute a class's static initializer until you actually touch something in the class. This applies to static nested classes, too. In the following example, the JLS guarantees the JVM will not initialize instance until someone calls getInstance():
8) How do you prevent for creating another instance of Singleton using reflection?
Open to all. In my opinion throwing exception from constructor is an option.
Answer: This is similar to previous interview question. Since constructor of Singleton class is supposed to be private it prevents creating instance of Singleton from outside but Reflection can access private fields and methods, which opens a threat of another instance. This can be avoided by throwing Exception from constructor as “Singleton already initialized”
9) How do you prevent for creating another instance of Singleton during serialization?
http://blog.davidehringer.com/testing/test-driven-development/unit-testing-singletons/
Some would say it is better in the sense that it has complete control of the object instantiation and ensures that there is one and only one instance of the class, but others feel that it is an anti-pattern since the instantiation part should not be the responsibility of the class itself
https://www.infoworld.com/article/3112025/application-development/design-patterns-that-i-often-avoid-singleton.html
https://ttmm.io/tech/singleton-alternative/
The entire point of a Singleton is to prevent multiple instances of your object from living together in the same context.
Read full article from Java Singleton Design Pattern Best Practices with Examples
不使用synchronized和lock,如何实现一个线程安全的单例?(二)
如果不那么吹毛求疵的话,可以使用枚举、静态内部类以及饿汉模式来实现单例模式。见:不使用synchronized和lock,如何实现一个线程安全的单例?
但是,上面这几种方法其实底层也都用到了
但是,上面这几种方法其实底层也都用到了
synchronized
,那么有没有什么办法可以不使用synchronized
和lock
,如何实现一个线程安全的单例?
答案是有的,那就是
CAS
。关于CAS
,我博客中专门有一篇文章介绍过他,很多乐观锁都是基于CAS
实现的CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
在JDK1.5 中新增
java.util.concurrent
(J.U.C)就是建立在CAS之上的。相对于对于synchronized
这种阻塞算法,CAS是非阻塞算法的一种常见实现。所以J.U.C在性能上有了很大的提升。
用CAS的好处在于不需要使用传统的锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。
CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销
CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销
Singleton using Enum in Java
public enum EasySingleton{
INSTANCE;
}
Enum Singletons handled Serialization by themselves
Creation of Enum instance is thread-safe
As stated in point 1 since creatino of Enum instance is thread-safe by default you don't need to worry about double checked locking.
Eager initialization
Static block initialization ==> to handle exception during initialization
https://hellosmallworld123.wordpress.com/2014/07/28/singleton-object-design-pattern/
Static class:
Only nested classes can be static. By doing so you can use the nested class without having an instance of the outer class. a static class must have all its members static. It is different from singleton
https://hellosmallworld123.wordpress.com/2014/05/21/threads-and-locks/Only nested classes can be static. By doing so you can use the nested class without having an instance of the outer class. a static class must have all its members static. It is different from singleton
try finally ?
public
class
singleton {
singleton s;
Lock lock =
new
ReentrantLock();
// lock
private
singleton() {}
// override the default constructor.
public
singleton getInstance() {
lock.lock();
if
(s ==
null
)
s =
new
singleton();
lock.unlock();
}
}
}
Double-Checked Locking (DCL) idiom
http://stackoverflow.com/questions/1879283/different-ways-to-write-singleton-in-java
tatic volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance == new Singleton();
}
}
return instance;
}
Orstatic Singleton instance;
public static synchronized Singleton getInstance() {
if (instance == null)
instance == new Singleton();
return instance;
}
Using volatile keyword to define singleton with double checked locking. The reason we use volatile keyword is because we want it to be visible to all the other thread as soon as the instance is updated.the double checked locking helps improve efficiency with the first lock (because it checks if instance is null or not before entering the synchronized block so that if eliminates the overhead of doing checking after the singleton is initialized. While the second check makes sure that creation of the instance is atomic.
nitialization on Demand Holder (IODH) idiom
requires very little code and has zero synchronization overhead. Zero, as in even faster than volatile. IODH requires the same number of lines of code as plain old synchronization, and it's faster than DCL!
IODH utilizes lazy class initialization. The JVM won't execute a class's static initializer until you actually touch something in the class. This applies to static nested classes, too. In the following example, the JLS guarantees the JVM will not initialize instance until someone calls getInstance():
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
http://javarevisited.blogspot.sg/2011/03/10-interview-questions-on-singleton.html8) How do you prevent for creating another instance of Singleton using reflection?
Open to all. In my opinion throwing exception from constructor is an option.
Answer: This is similar to previous interview question. Since constructor of Singleton class is supposed to be private it prevents creating instance of Singleton from outside but Reflection can access private fields and methods, which opens a threat of another instance. This can be avoided by throwing Exception from constructor as “Singleton already initialized”
9) How do you prevent for creating another instance of Singleton during serialization?
Another problem with conventional Singletons are that once you implement serializable interface they are no longer remain Singleton because readObject() method always return a new instance just like constructor in Java. you can avoid that by using readResolve() method and discarding newly created instance by replacing with Singeton as shwon in below example :
//readResolve to prevent another instance of Singleton
private Object readResolve(){
return INSTANCE;
}
This can become even more complex if your Singleton Class maintain state, as you need to make them transient, but witn Enum Singleton, Serialization is guarnateed by JVM.
Singleton using Enum in Java
http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
By default creation of Enum instance is thread safe but any other method on Enum is programmers responsibility.
public enum EasySingleton{
INSTANCE;
}
2) Enum Singletons handled Serialization by themselves
Another problem with conventional Singletons are that once you implement serializable interface they are no longer remain Singleton because readObject() method always return a new instance just like constructor in Java.
private Object readResolve(){
return INSTANCE;
}
3) Creation of Enum instance is thread-safe
Singleton is one of the most common design patterns, but it has many implementation variants: lazy Instantiation, eager Instantiation, static holder idiom, and etc. Static holder idiom is my favorite.
http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
By default creation of Enum instance is thread safe but any other method on Enum is programmers responsibility.
public enum EasySingleton{
INSTANCE;
}
2) Enum Singletons handled Serialization by themselves
Another problem with conventional Singletons are that once you implement serializable interface they are no longer remain Singleton because readObject() method always return a new instance just like constructor in Java.
private Object readResolve(){
return INSTANCE;
}
3) Creation of Enum instance is thread-safe
public
enum
SingletonEnum {
INSTANCE;
public
void
doStuff(){
System.out.println(
"Singleton using Enum"
);
}
}
Singleton is one of the most common design patterns, but it has many implementation variants: lazy Instantiation, eager Instantiation, static holder idiom, and etc. Static holder idiom is my favorite.
package org.codeexample.javacode.singletons; import java.io.Serializable; public class SinletonVariants { } /** * When the singleton class is referenced, its instance would not be created, * and also Java guarantees that the class initialization is atomic. * * So using the static holder idiom, we combine the benefit of lazy * instantiation and no further synchronization after the instance is created, * <p> * My favorite, always use this one. */ class SingletonHolderIdiom { private SingletonHolderIdiom() { } private static class SingletonHolder { private static final SingletonHolderIdiom instance = new SingletonHolderIdiom(); } public static SingletonHolderIdiom getInstance() { return SingletonHolder.instance; } } /** * To maintain the singleton guarantee, you have to declare all instance fields * transient and provide a readResolve method that directly return the static * instance, also you must use eager instantiation. * <p> * see Effective Java 2nd Edition: <br> * Item 3: Enforce the singleton property with a private constructor or an enum * type */ class SerializableSingleton implements Serializable { private static final long serialVersionUID = 1L; private static SerializableSingleton instance = new SerializableSingleton(); private SerializableSingleton() { } public static SerializableSingleton getInstance() { return instance; } // readResolve method to preserve singleton property private Object readResolve() { return instance; } } /** * This variant avoids the drawback of eager instantiation, as no resources are * allocated before the instance is actually accessed, but further * synchronization might seem unnecessary and expensive after the instance is * already constructed. * */ class SingletonLazyInstantiation { private static SingletonLazyInstantiation instance; private SingletonLazyInstantiation() { } public static synchronized SingletonLazyInstantiation getInstance() { if (instance == null) { instance = new SingletonLazyInstantiation(); } return instance; } } /** * This would initialize this singleton class eagerly, when the class is loaded * at first time. Thus, it may happen that the singleton instance is constructed * even if it is not accessed. This is a drawback, especially when the * construction is complex and time/resource consuming. The good part of this * variant is its simplicity. * */ class SingletonEagerInstantiation { private static SingletonEagerInstantiation instance = new SingletonEagerInstantiation(); private SingletonEagerInstantiation() { } public static SingletonEagerInstantiation getInstance() { return instance; } }
http://blog.davidehringer.com/testing/test-driven-development/unit-testing-singletons/
To start, singletons are a form of global state that is to be avoided. They carry state across the entire execution of the program making both testing and debugging difficult. It becomes hard to execute tests in isolation because they may modify the state of the singleton in ways that undesirably ties tests to a strict execution order. Beyond problems with global state, objects that use singletons are highly coupled to the both the way the singleton is instantiated and the way it is implemented. It isn’t possible to test an object that depends on a singleton without testing (or in someway relying on the behavior of) the singleton as well. Furthermore, this coupling is hidden from the user of the object. To correctly interact with the class depending on the singleton, a dependency that is not explicit in its interface, you must often also understand the behavior of the singleton. In other words, the state and behavior of the singleton can affect the behavior of the depending object as well as transitive side effects.
By using reflection in one of your JUnit setup (i.e. @Before) methods, you can make sure each test starts with an uninitialized singleton and your tests are no longer affecting each other.
@Before public void resetMySingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field instance = MySingleton.class.getDeclaredField("instance"); instance.setAccessible(true); instance.set(null, null); }https://social.technet.microsoft.com/wiki/contents/articles/19710.unit-testing-of-singleton-objects.aspx
Some would say it is better in the sense that it has complete control of the object instantiation and ensures that there is one and only one instance of the class, but others feel that it is an anti-pattern since the instantiation part should not be the responsibility of the class itself
https://www.infoworld.com/article/3112025/application-development/design-patterns-that-i-often-avoid-singleton.html
Dependencies are hidden
One of the most important design considerations of the Singleton design pattern is that a Singleton class should be thread safe and static in nature. In using the Singleton pattern, you use a global instance and hide the dependencies. The dependencies are hidden inside your code and are not exposed through interfaces. As the application’s KLOC grows, this becomes increasingly difficult over time to inspect the code understand the dependencies and how the objects are related to each other. Also, providing a global access to an instance to avoid it being passed around in the application is considered a bad design practice -- an example of a code smell. You can actually get around the need of having to use the Singleton design pattern by using dependency injection in your applications.
Unit tests become difficult
The entire point of a Singleton is to prevent multiple instances of your object from living together in the same context.
Singletons are also inherently inextensible – you cannot subclass a Singleton. As your application grows, however, the need to subclass an object can and will come up.
https://www.quora.com/What-are-the-singleton-alternatives
https://gist.github.com/rwoloszyn/adc289dd596283c2d635658af59ac3b2
The usual alternative to achieving that purpose is dependency injection. For your example, the Cart Manager, you may have an object called CartManager. You may have a CheckOut class which requires the CartManager, so you either
- Pass the CartManager to the CheckOut class through the constructor
- Assign the CartManager to be one the CheckoutClass’s member
In this way, we have made the CartManager a dependency for the CheckOut class. Managing dependencies manually can be tiresome, hence there are many dependency injection containers out there. There’s a few choices for every platform.
First, it is important to separate the “need for one of something in my system” from the “singleton pattern”. It’s perfectly reasonable to want one of something but to avoid using the singleton pattern. In other words, the problem is in the pattern, not in the goal.
When a singleton seems like the answer, I find it is often wiser to:
- Create an interface and a default implementation of your singleton
- Construct a single instance of your default implementation at the “top” of your system. This might be in a Spring config, or in code, or defined in a variety of ways depending on your system.
- Pass the single instance into each component that needs it (dependency injection)
This alternative will give you the effects of a singleton, but makes the dependencies clear in the components that need it, allows a singleton to be mocked (via the interface), subclassed, proxied, and tested.
https://gist.github.com/rwoloszyn/adc289dd596283c2d635658af59ac3b2
Read full article from Java Singleton Design Pattern Best Practices with Examples