Implementation of the single-instance mode in Python Design Mode and Its Application in Tornado

Source: Internet
Author: User
This article mainly introduces the implementation of the single-instance mode in the Python Design Mode and Its Application in Tornado, and explains the problems related to the thread control used in the single-instance mode to design the Tornado framework, for more information, see Implementation of Singleton Mode
Bind a class instance to a class variable

class Singleton(object):  _instance = None  def __new__(cls, *args):    if not isinstance(cls._instance, cls):      cls._instance = super(Singleton, cls).__new__(cls, *args)    return cls._instance

However, after the subclass is inherited, You can override _ new _ to lose the singleton feature.

class D(Singleton):  def __new__(cls, *args):    return super(D, cls).__new__(cls, *args)

Implement with a decorator

def singleton(_cls):  inst = {}  def getinstance(*args, **kwargs):    if _cls not in inst:      inst[_cls] = _cls(*args, **kwargs)    return inst[_cls]  return getinstance@singletonclass MyClass(object):  pass

The problem is that after the decoration, the returned result is not a class but a function. Of course, you can define a class in singleton to solve the problem, but this is very troublesome.

Use _ metaclass __, which is the most recommended method

class Singleton(type):  _inst = {}    def __call__(cls, *args, **kwargs):    if cls not in cls._inst:      cls._inst[cls] = super(Singleton, cls).__call__(*args)    return cls._inst[cls]class MyClass(object):  __metaclass__ = Singleton


Use of Singleton mode in Tornado
Let's take a look at the singleton mode in tornado. IOLoop:

class IOLoop(object):  @staticmethod  def instance():    """Returns a global `IOLoop` instance.Most applications have a single, global `IOLoop` running on themain thread. Use this method to get this instance fromanother thread. To get the current thread's `IOLoop`, use `current()`."""    if not hasattr(IOLoop, "_instance"):      with IOLoop._instance_lock:        if not hasattr(IOLoop, "_instance"):          # New instance after double check          IOLoop._instance = IOLoop()    return IOLoop._instance

Why is double check required? Here is a simple Singleton mode. Let's take a look at the Code:

class Singleton(object):  @staticmathod  def instance():    if not hasattr(Singleton, '_instance'):      Singleton._instance = Singleton()    return Singleton._instance

In Python, you can post in the true constructor _ new:

class Singleton(object):  def __new__(cls, *args, **kwargs):    if not hasattr(cls, '_instance'):      cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)    return cls._instance

This situation seems to be good, but it cannot be guaranteed to be useful in a multi-threaded environment. See the figure below:

This is obviously not feasible after multithreading occurs.

1. Lock to synchronize threads
Lock code:

import threadingclass Singleton(object):  _instance_lock = threading.Lock()    @staticmethod  def instance():    with Singleton._instance_lock:      if not hasattr(Singleton, '_instance'):        Singleton._instance = Singleton()    return Singleton._instance

This does solve the problem of multithreading, but we only need to lock the instance during instantiation, and Singleton in other cases. _ The instance already exists and does not need to be locked. At this time, the other threads that want to obtain the Singleton instance still have to wait. The existence of the lock significantly reduces the efficiency and performance loss.

2. Global Variables
In Java/C ++, global variables can also be used to solve the above locking (synchronization) problems:

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

In Python, this is the case:

class Singleton(object):  @staticmethod  def instance():    return _g_singleton_g_singleton = Singleton()# def get_instance():# return _g_singleton

However, if this class occupies a large amount of resources, it will not be cost-effective and the Python code will be ugly ......

So there is a singleton mode of double check like tornado. IOLoop. instance. In the case of multiple threads, neither the performance decrease caused by synchronization (locking) nor the resource waste caused by direct instantiation of global variables.

3. decorator

If you use a decorator, it will be like this:

import functoolsdef singleton(cls):  ''' Use class as singleton. '''  cls.__new_original__ = cls.__new__  @functools.wraps(cls.__new__)  def singleton_new(cls, *args, **kw):    it = cls.__dict__.get('__it__')    if it is not None:      return it    cls.__it__ = it = cls.__new_original__(cls, *args, **kw)    it.__init_original__(*args, **kw)    return it  cls.__new__ = singleton_new  cls.__init_original__ = cls.__init__  cls.__init__ = object.__init__  return cls## Sample use:#@singletonclass Foo:  def __new__(cls):    cls.x = 10    return object.__new__(cls)  def __init__(self):    assert self.x == 10    self.x = 15assert Foo().x == 15Foo().x = 20assert Foo().x == 20

def singleton(cls):  instance = cls()  instance.__call__ = lambda: instance  return instance## Sample use#@singletonclass Highlander:  x = 100  # Of course you can have any attributes or methods you like.Highlander() is Highlander() is Highlander #=> Trueid(Highlander()) == id(Highlander) #=> TrueHighlander().x == Highlander.x == 100 #=> TrueHighlander.x = 50Highlander().x == Highlander.x == 50 #=> True

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.