Python: thread-safe implementation of a singleton
Sometimes the singleton design pattern is required to limit resources usage like the number of connections to a database or an external API service.
In other languages this design pattern could be difficult to write I mean specifically to satisfy the thread safety but for Python it’s not really the case. Here is an easy implementation.
Implementation
1import logging
2import threading
3
4class MySingleton(object):
5 _instance: object = None
6 _lock: threading.Lock = threading.Lock()
7
8 def __new__(cls):
9 """Create a new instance"""
10 if MySingleton._instance is None:
11 with MySingleton._lock:
12 if MySingleton._instance is None:
13 MySingleton._instance = super(MySingleton, cls).__new__(cls)
14 MySingleton._instance._initialized = False
15
16 return MySingleton._instance
17
18 def __init__(self):
19 """Initialize the instance"""
20 if self._initialized is False:
21 self._logger = logging.getLogger(self.__class__.__name__)
22 self._count = 0
23
24 self._initialized = True
25
26 self._logger.debug("using instance: %s" % self._instance)
27
28 def increment(self):
29 """Increment the counter"""
30 self._count += 1
31
32 self._logger.debug("count = %d" % self._count)
Test
To prove that it works let’s try in a python console:
>>> from code import MySingleton
>>> logging.basicConfig(level=logging.DEBUG, handlers=[logging.StreamHandler()])
>>> a = MySingleton()
DEBUG:MySingleton:using instance: <__main__.MySingleton object at 0x7f8bee80c550>
>>> b = MySingleton()
DEBUG:MySingleton:using instance: <__main__.MySingleton object at 0x7f8bee80c550>
>>> a.increment()
DEBUG:MySingleton:count = 1
>>> a.increment()
DEBUG:MySingleton:count = 2
>>> b.increment()
DEBUG:MySingleton:count = 3
As you can see the objects a and b share the same instance.