How to ensure the safety of singleton thread in a multi-thread

   How to ensure the safety of singleton thread in a multi-thread

        Knowledge of big data, distributed, high concurrency must learn how to thread basis. Here to talk about how to design a singleton in the case of multi-threaded. In the 23 design patterns Singleton pattern is more common, write singleton in the case of non-multithreaded, it will be very few things to consider, but if a multi-threaded and single-case model together, consider things changed more, if improperly used (especially in the build environment) will result in serious consequences. So how safe is the singleton pattern is particularly important in multiple threads, here are the advantages and disadvantages of each approach and availability:

       1. Load immediately (starving mode)

        Load mode is immediately before calling the getInstance () method, the instance is created, for example:

the MyObject class {public
 // load immediately embodiment mode == starving
Private new new static the MyObject the MyObject the myObject = ();
Private the MyObject () {
}
public static the MyObject the getInstance () {
return the myObject;
}
}

-------------------------------------------------------------------

public class MyThread extends Thread{
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}

------------------------------------------------------------------

public class Run {
   public static void main(String[] args) {
 MyThread t1=new MyThread();
 MyThread t2=new MyThread();
 MyThread t3=new MyThread();
 t1.start();
 t2.start();
 t3.start();
}
}

     Print Console:

714682869
714682869
714682869

    3 console prints out the hashCode identical, only one object is described, which is immediately loaded singleton. This model has a drawback, however, is that there are not other instance variables, because getInstance () method is not synchronized, so the non-thread-safety issues that may arise.

   2. Load delay (lazy mode)

    Lazy loading is to create instances, Example getInstance () method:

     public class MyObject {
private static MyObject myObject;
private MyObject(){
     }
 public static MyObject getInstance(){
// 延迟加载
 if(myObject!=null){  
}else{
myObject=new MyObject();
 }
return myObject;
     }
}

-------------------------------------------------------------------

public class MyThread extends Thread{
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}

-------------------------------------------------------------------

public class Run {
public static void main(String[] args) {
MyThread t1=new MyThread();
t1.start();
}
}

     Print Console:

1701381926

    One example of console print out. Disadvantages: In a multi-threaded environment, where multiple instances will be taken, with the intention Singleton pattern deviates. Therefore, in a multithreaded environment, this sample code is wrong.

    3. A method of modifying a delay synchronized Loading

    public class MyObject {
private static MyObject myObject;
private MyObject(){
}
synchronized public static MyObject getInstance(){
try {
if(myObject!=null){
}else{
Thread.sleep(3000);
myObject=new MyObject();
}
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
return myObject;
}
}

 -------------------------------------------------------------------

public class MyThread extends Thread{
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}      

-------------------------------------------------------------------

public class Run {
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();
t2.start();
t3.start();
}
}

     Print Console:

 1069480624
1069480624
1069480624

     Although got the same example, but we know synchronized are synchronized, a thread must wait for another thread to perform after the release of the lock, affecting efficiency.

      4. Using the synchronization code block delay loading, the locking of the class

        public class MyObject {
private static MyObject myObject;
private MyObject(){
}
public static MyObject getInstance(){
try {
synchronized(MyObject.class){
if(myObject!=null){
}else{
Thread.sleep(3000);
myObject=new MyObject();
}
}
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
return myObject;
}
}

 -------------------------------------------------------------------

public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}

 -------------------------------------------------------------------

public class Run {
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();
t2.start();
t3.start();
}
}

       Print Console:

1743911840
1743911840
1743911840

       Although this code is correct, but getInstance () method in the code are synchronized, in fact, also a third way, and the same will reduce efficiency

       5. DCL double checks the lock mechanism

        DCL double check that the use of the volatile keyword locking mechanism (the variable is visible in the plurality of threads) and the object synchronized code block modification

       public class MyObject {
    private volatile static MyObject myObject;
    private MyObject(){
    }
    public static MyObject getInstance(){
    try {
if(myObject!=null){
}else{
Thread.sleep(3000);
synchronized(MyObject.class){
if(myObject==null){
myObject=new MyObject();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
// TODO: handle exception
}
    return myObject;
    }
}

 -------------------------------------------------------------------

public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}    

 -------------------------------------------------------------------

public class Run {
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();
t2.start();
t3.start();
}
}

     Print Console:

798941612
798941612
798941612

      Use DCL double check the lock mechanism, successfully resolved the problem of multi-threaded lazy loading pattern encountered achieve a thread-safe. In fact, using a combination of DCL most multithreaded singleton pattern case is a good solution.

       6. The built-in classes implemented using static Singleton

       public class MyObject {
// 内部类方式
private static class MyObjectHandler{
private static MyObject myObject=new MyObject();
}
private MyObject(){

}
public static MyObject getInstance(){
return MyObjectHandler.myObject;
}
}

-------------------------------------------------------------------

public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}

 -------------------------------------------------------------------

public class Run {
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();
t2.start();
t3.start();

}
}

    Print Console:

1743911840
1743911840
1743911840

         Built-in classes can be solved using the static multi-threaded mode, single cases of non-thread-safe issue and realize the thread-safe, but if the object is serialized can not achieve the desired effect.

       7. serialization and deserialization singleton

 Methods need readResolve

        public class MyObject implements Serializable{
private static final long serialVersionUID=888L;
// 内部类
private static class MyObjectHandler{
private static final MyObject myObject=new MyObject();
}
private MyObject(){

}
public static MyObject getInstance(){
return MyObjectHandler.myObject;
}
 protected Object readResolve() throws ObjectStreamException {
 System.out.println("调用了readResolve方法");
return MyObjectHandler.myObject;
 }
}

-------------------------------------------------------------------

public class SaveAndRead {
public static void main(String[] args) {
try {
MyObject myObject=MyObject.getInstance();
FileOutputStream fosRef=new FileOutputStream(new File("myObjectFile.txt"));
ObjectOutputStream oosRef=new ObjectOutputStream(fosRef);
oosRef.writeObject(myObject);
oosRef.close();
fosRef.close();
System.out.println(myObject.hashCode());
} catch (FileNotFoundException e) {
// TODO: handle exception
} catch(IOException e){
e.printStackTrace();
}
try {
FileInputStream fisRef=new FileInputStream(new File("myObjectFile.txt"));
ObjectInputStream iosRef=new ObjectInputStream(fisRef);
MyObject myObject=(MyObject) iosRef.readObject();
iosRef.close();
fisRef.close();
System.out.println(myObject.hashCode());
} catch (FileNotFoundException e) {
// TODO: handle exception
} catch(IOException e){
e.printStackTrace();
} catch(ClassNotFoundException e){
e.printStackTrace();
}
}
}   

      Print Console:

 1988716027
call readResolve method
1988716027

      After calling readResolve way is a single case, and if we commented readResolve method,

      Print Console:

977199748
536468534

       8. implemented using static block Singleton

        public class MyObject {
private static MyObject instance=null;
private MyObject(){

}
static {
instance=new MyObject();
}
public static MyObject getInstance(){
return instance;
}
}

-------------------------------------------------------------------

public class MyThread extends Thread{

public void run(){
for (int i = 0; i <5; i++) {
System.out.println(MyObject.getInstance().hashCode());
}
}
}

-------------------------------------------------------------------

public class Run {
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();
t2.start();
t3.start();

}
}

   Print Console:

798941612
798941612
798941612

 

Guess you like

Origin www.cnblogs.com/whymoney1000/p/11420593.html