Simultaneous calls to singleton class methods

I have a singleton class:

public class Singleton { private static Singleton istance = null; private Singleton() {} public synchronized static Singleton getSingleton() { if (istance == null) istance = new Singleton(); return istance; } public void work(){ for(int i=0; i<10000; i++){ Log.d("-----------", ""+i); } } } 

And several threads call the work () function:

 public class Main { public static void main(String[] args) { new Thread (new Runnable(){ public void run(){ Singleton s = Singleton.getSingleton(); s.work();} }).start(); System.out.println("main thread"); new Thread(new Runnable() { public void run() { Singleton s = Singleton.getSingleton(); s.work(); } }).start(); } } 

I noticed that two threads work simultaneously, as if two work functions were being performed simultaneously.

I want the last thread to start instead of the previous thread, and not simultaneously. Is it possible in java to make a second call to override the memory size of the first call?

+4
source share
5 answers

Your getSingleton() method tries to lazily initialize an instance of SINGLETON, but it has the following problems:

  • Variable access not synchronized
  • The variable is not volatile
  • You do not use double lock check

therefore, the AMY race condition causes the creation of two instances.

It was best and easier to safely lazily initialize a singleton without synchronization:

 private static class Holder { static Singleton instance = new Singleton(); } public static Singleton getSingleton() { // Note: "synchronized" not needed return Holder.instance; } 

This is thread safe because the java class loader contract is that all classes have static initialization before they can be used. In addition, the class loader does not load the class until it is referenced. If two calls to the getSingleton() stream at the same time, the Holder class will still be loaded only once, and thus new Singleton() will be executed only once.

This is still lazy because the Holder class only refers to the getSingleton() method, so the Holder class will only load the first time getSingleton() called.

No synchronization is required because this code uses the internal loader synchronization of the class, which is bullet proof.


This code template is the only way to fly with single player games. It:

  • The fastest (no sync)
  • The safest (depends on the safety of the industrial strength class loader)
  • Cleanest (smallest code - double locking check - ugly and lots of lines for what it does)


Another similar code (equally safe and fast) is to use enum with a single instance, but I find this inconvenient and the intention is less clear.

+12
source

As pointed out by @mit comment, your getSingleton() method must be synchronized . The reason for this is that multiple threads may request an instance at the same time, and the first thread will still initialize the object, and the link will be zero when the next thread checks. This will create two instances.

 public static synchronized Singleton getSingleton() { if (istance == null) istance = new Singleton(); return istance; } 

Marking your method as synchronized will only block and allow one thread at a time. This should solve your problem.

+4
source

Use synchronized for factory method

 public class Singleton { private static Singleton istance = null; private final Singleton() {} // avoid overrides public static synchronized Singleton getSingleton() { if (istance == null) istance = new Singleton(); return istance; } public void work() { // not static, otherwise there no need for the singleton // ... } } 

or just use a closed final initializer (instantiation will occur during class loading)

 public class Singleton { private static final Singleton istance = new Singleton(); // class-load initialization private final Singleton() {} public static Singleton getSingleton() { // no need for synchronized return istance; } public void work() { // ... } } 
0
source

Resource owner specified in Java Concurrency In practice: http://www.javaconcurrencyinpractice.com/ is the best non-blocking singleton template. The singleton is lazily initialized (both the SingletonHolder and Singleton classes are loaded at run time, when the getInstance () method is called for the first time), and the access method is either not blocked.

 public class SingletonFactory { private static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonFactory.SingletonHolder.instance; } static class Singleton{ } 

}

0
source

I came up with this code that does practically what I need. Orignal question: "Is it possible to do the following without using threads? But instead, directly manipulating memory with the language?" If the answer is no, maybe you can help me improve the following:

 public class Main { private static Thread t; public static void main(String[] args) { work(); for (int i =0;i<100; i++); System.out.println("oooooooooooooooooooooooooooooooooooooooooo"); for (int i =0;i<100; i++); work(); for (int i =0;i<500; i++); System.out.println("oooooooooooooooooooooooooooooooooooooooooo"); } public static void work(){ if (t != null) t.interrupt(); t= new Thread (new Runnable(){ public void run(){ // Pause for 4 seconds try { Thread.sleep(600); } catch (InterruptedException e) { // We've been interrupted: no more messages. return; } for(int i=0; i<10000; i++){ System.out.println(i); } } }); t.start(); } } 

This code is useful for "debounce" multiple calls to the listener, triggering in a packet on the user inputs. It has flaws, it uses the sleep function. Sleep time should be high enough so that the events in the package do not start the execution of a laborious task (only the last event should). Unfortunately, there is no guarantee that this can happen even with long sleep times.

0
source

Source: https://habr.com/ru/post/1439590/


All Articles