1.多线程执行单例模式时,容易出bug

  1. import threading
  2. import time
  3. class Singleton:
  4. instance = None
  5. def __init__(self, name):
  6. self.name = name
  7. def __new__(cls, *args, **kwargs):
  8. if cls.instance:
  9. return cls.instance
  10. time.sleep(0.1)
  11. """这里:第一个线程没来得及创建空对象给instance,其他线程发现是空
  12. 都着急创建instance空对象,会导致创建出多个空对象
  13. 和我们希望出现的单例模式背道而驰,此时应该在这个创建之前加锁
  14. """
  15. cls.instance = object.__new__(cls)
  16. return cls.instance
  17. def task():
  18. obj = Singleton('x')
  19. print(obj)
  20. for i in range(10):
  21. t = threading.Thread(target=task)
  22. t.start()

2.加锁解决bug

  1. import threading
  2. import time
  3. class Singleton:
  4. instance = None
  5. lock_object = threading.RLock()
  6. def __init__(self, name):
  7. self.name = name
  8. def __new__(cls, *args, **kwargs):
  9. with lock_object:
  10. if cls.instance:
  11. return cls.instance
  12. time.sleep(0.1)
  13. """这里:第一个线程没来得及创建空对象给instance,其他线程发现是空
  14. 都着急创建instance空对象,会导致创建出多个空对象
  15. 和我们希望出现的单例模式背道而驰,此时应该在这个创建之前加锁
  16. """
  17. cls.instance = object.__new__(cls)
  18. return cls.instance
  19. def task():
  20. obj = Singleton('x')
  21. print(obj)
  22. for i in range(10):
  23. t = threading.Thread(target=task)
  24. t.start()

3.加判断提升锁的性能

  1. import threading
  2. import time
  3. class Singleton:
  4. instance = None
  5. lock_object = threading.RLock()
  6. def __init__(self, name):
  7. self.name = name
  8. def __new__(cls, *args, **kwargs):
  9. if cls.instance:
  10. return cls.instance
  11. with lock_object:
  12. """这里的if instance必须加上
  13. 因为如果不加的话,前面已经判断过是none,当锁释放的时候
  14. 会重新创建对象
  15. """
  16. if cls.instance:
  17. return cls.instance
  18. time.sleep(0.1)
  19. """这里:第一个线程没来得及创建空对象给instance,其他线程发现是空
  20. 都着急创建instance空对象,会导致创建出多个空对象
  21. 和我们希望出现的单例模式背道而驰,此时应该在这个创建之前加锁
  22. """
  23. cls.instance = object.__new__(cls)
  24. return cls.instance
  25. def task():
  26. obj = Singleton('x')
  27. print(obj)
  28. for i in range(10):
  29. t = threading.Thread(target=task)
  30. t.start()