I have wrote two classes. The first class MySingletonTSafe is thread-safe because I use threading.Lock() to control how to call the method that creates the instance. But I'm not sure whether the second class MySingletonNTSafe is thread-safe. How could the sencond class be proved not thread-safe if it is?
I have found the thread Creating a singleton in python but it couldn't solve my puzzle.
The following is my code:
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
import threading
import Queue
import time
import random
class MySingletonTSafe(object):
"""implement Singleton pattern, thread-safe"""
_instance = None
_lock = threading.Lock()
def __new__(cls):
if MySingletonTSafe._instance is None:
with MySingletonTSafe._lock:
if MySingletonTSafe._instance is None:
MySingletonTSafe._instance = super(MySingletonTSafe, cls).__new__(cls)
return MySingletonTSafe._instance
def __init__(self):
MySingletonTSafe._instance = self
class MySingletonNTSafe(object):
"""implement Singleton pattern, not-thread-safe"""
_instance = None
def __new__(cls):
if MySingletonNTSafe._instance is None:
# time.sleep(random.randint(1, 10))
MySingletonNTSafe._instance = super(MySingletonNTSafe, cls).__new__(cls)
return MySingletonNTSafe._instance
def __init__(self):
MySingletonNTSafe._instance = self
class Test(object):
"""Test whether the class MySingleton works"""
def __init__(self, tnum=3):
self.tnum = tnum
self.queue_st = Queue.Queue()
self.queue_nst = Queue.Queue()
def run(self):
threads_s = [threading.Thread(target=self._run_st) for i in xrange(self.tnum)]
for t in threads_s:
t.start()
t.join()
threads_ns = [threading.Thread(target=self._run_nst) for i in xrange(self.tnum)]
for t in threads_ns:
t.start()
t.join()
def _run_st(self):
# thread-safe case
obj = MySingletonTSafe()
self.queue_st.put(obj)
def _run_nst(self):
# not-thread-safe case
obj = MySingletonNTSafe()
self.queue_nst.put(obj)
if __name__ == '__main__':
test = Test(tnum=10)
test.run()
objs_st = []
while not test.queue_st.empty():
objs_st.append(test.queue_st.get())
last = objs_st.pop()
for obj in objs_st:
if not last == obj:
print('NOT IDENTICAL')
break
else:
print('IDENTICAL')
objs_nst = []
while not test.queue_nst.empty():
objs_nst.append(test.queue_nst.get())
last = objs_nst.pop()
for obj in objs_nst:
if not last == obj:
print('NOT IDENTICAL')
break
else:
print('IDENTICAL')