zoukankan      html  css  js  c++  java
  • 类的多线程下实现单例类

     

    这两天在看自己之前写的代码,所以正好把用过的东西整理一下,单例模式,在日常的代码工作中也是经常被用到,

    所以这里把之前用过的不同方式实现的单例方式整理一下

    装饰器的方式

    这种方式也是工作中经常用的一种,用起来也比较方便,代码实现如下

    复制代码
    def Singleton(cls):
        _instance = {}
    
        def _singleton(*args, **kwargs):
            if cls not in _instance:
                _instance[cls] = cls(*args, **kwargs)
            return _instance[cls]
    
        return _singleton
    复制代码

    如果我们工作的一个类需要用单例就通过类似下面的方式实现即可:

    @Singleton
    class A(object):
    
        def __init__(self, x):
            self.x = x

    我个人还是挺喜欢这种方式的

    类的方式实现

    这里其实有一些问题就需要注意了,先看一下可能出现的错误代码

    复制代码
    class Member(object):
    
        @classmethod
        def instance(cls, *args, **kwargs):
            if not hasattr(Member, "_instance"):
                Member._instance = Member(*args, **kwargs)
            return Member._instance
    复制代码

    乍一看这个类好像已经实现了单例,但是这里有一个潜在的问题,就是如果是多线程的情况,这样写就会有问题了,尤其是在当前类的初始化对象里有一些耗时操作时候

    例如下面代码:

    复制代码
    #! /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()
    复制代码

    这段代码的执行结果会出现实例化了多个对象,导致你写的单例就没起到作用

    当然自然而然我们会想起加锁,通过锁来控制,所以我们将上面代码进行更改:

    复制代码
    #! /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
    复制代码

    这样就很好的实现一个可以多线程使用的单例

     
     
  • 相关阅读:
    C语言-if语句
    C语言-表达式
    C语言-基础
    Java for LeetCode 187 Repeated DNA Sequences
    Java for LeetCode 179 Largest Number
    Java for LeetCode 174 Dungeon Game
    Java for LeetCode 173 Binary Search Tree Iterator
    Java for LeetCode 172 Factorial Trailing Zeroes
    Java for LeetCode 171 Excel Sheet Column Number
    Java for LeetCode 169 Majority Element
  • 原文地址:https://www.cnblogs.com/laogao123/p/10140533.html
Copyright © 2011-2022 走看看