I have an implementation of a Singleton pattern like this, with a very simplified use-case to more easily illustrate what I am trying to do:
import threading
from dataclasses import dataclass
lock = threading.Lock()
class Singleton(type):
_instances = {} # type: ignore
def __call__(cls, *args): # type: ignore
with lock:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args)
return cls._instances[cls]
@dataclass
class Foo(metaclass=Singleton):
var: bool
def change_Foo(signal): # type: ignore
foo = Foo(True)
while True:
if signal[0]:
foo.var = not foo.var
signal[0] = False
def main(): # type: ignore
foo = Foo(True)
signal_0 = [False]
signal_1 = [False]
threading.Thread(target=change_Foo, args=(signal_0,), daemon=True).start()
threading.Thread(target=change_Foo, args=(signal_1,), daemon=True).start()
assert foo.var is True
signal_0[0] = True
time.sleep(0.1)
assert foo.var is False
signal_1[0] = True
time.sleep(0.1)
assert foo.var is True
signal_0[0] = True
time.sleep(0.1)
assert foo.var is False
main() # type: ignore
The above code implements a singleton pattern using a metaclass as described here. I also combined this with a lock controller as described here.
Is this singleton pattern implementation truly thread safe? If not, what is a thread safe implementation of singleton pattern in python?
I guess with this implementation, the lock
is only ever used when creating a new Foo
object, but not when accessing a field variable of the class.
Is it possible to apply a lock for when accessing a field member of a class?
I believe I have to overwrite some function like __getitem__()
in class Foo
(or maybe in class Singleton
?) such that when accessing a field variable of Foo
, they have to acquire a lock.
Also in my class Singleton
implementation I use a global lock
, is it possible to make this lock
have a local implementation inside of main() instead of having lock
be a global variable?