这两天在看本身以前写的代码,因此正好把用过的东西整理一下,单例模式,在平常的代码工做中也是常常被用到,python
因此这里把以前用过的不一样方式实现的单例方式整理一下多线程
这种方式也是工做中常常用的一种,用起来也比较方便,代码实现以下dom
def Singleton(cls): _instance = {} def _singleton(*args, **kwargs): if cls not in _instance: _instance[cls] = cls(*args, **kwargs) return _instance[cls] return _singleton
若是咱们工做的一个类须要用单例就经过相似下面的方式实现便可:spa
@Singleton class A(object): def __init__(self, x): self.x = x
我我的仍是挺喜欢这种方式的线程
这里其实有一些问题就须要注意了,先看一下可能出现的错误代码code
class Member(object): @classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance
乍一看这个类好像已经实现了单例,可是这里有一个潜在的问题,就是若是是多线程的状况,这样写就会有问题了,尤为是在当前类的初始化对象里有一些耗时操做时候对象
例以下面代码:blog
#! /usr/bin/env python3 # .-*- coding:utf-8 .-*- import time import threading import random class Member(object): def __init__(self): time.sleep(random.randint(1,3)) @classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance def task(arg): obj = Member.instance() print(obj) for i in range(5): t = threading.Thread(target=task, args=[i,]) t.start()
这段代码的执行结果会出现实例化了多个对象,致使你写的单例就没起到做用utf-8
固然天然而然咱们会想起加锁,经过锁来控制,因此咱们将上面代码进行更改:get
#! /usr/bin/env python3 # .-*- coding:utf-8 .-*- import time import threading import random class Member(object): _instance_lock = threading.Lock() def __init__(self): i = random.randint(1, 3) print(i) time.sleep(i) @classmethod def instance(cls, *args, **kwargs): with Member._instance_lock: if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance def task(): obj = Member.instance() print(obj) for i in range(5): threading.Thread(target=task,).start()
可是上面的代码还有一个问题,就是当咱们已经实例化过以后每次调用instance都会去请求锁,因此这点并很差,因此咱们将这部分代码再次更改:
@classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): with Member._instance_lock: if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance
这样就很好的实现一个能够多线程使用的单例