python 實現線程安全的單例模式


單例模式是一種常見的設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。

比如,服務器的配置信息寫在一個文件中online.conf中,客戶端通過一個 Config 的類來讀取配置文件的內容。如果在程序運行期間,有很多地方都需要使用配置文件的內容,那么每個調用配置文件的地方都會創建 Config的實例,這就導致系統中存在多個Config 的實例對象,在配置文件內容很多的情況下,我們就浪費了大量的內存做了同樣的事。事實上,對於Config類我們在程序運行期間時只需要一個實例對象即可,這時單例模式就是最好的選擇。

 

python的模塊就是天然的單例模式,這里我們使用修飾器來實現單例模式,以下是代碼實現

def Singleton(cls):
    instances = {}

    def get_instance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return get_instance

代碼也很簡單,將類傳入單例修飾器中,如果該類還未生成實例(instances中不存在該類),那么就生成一個新的實例返回,並記錄在instances中。如果已經instances中已經存在該類,那么直接返回實例instances[cls]。

 

那么這段代碼是完美的嗎?答案是否定的,這段代碼不是線程安全的。要實現線程安全需要配合鎖的使用,只有占有鎖的線程才能繼續訪問單例實例,看來我們需要再寫一個修飾器來實現線程安全了,以下是完整的代碼實現和簡單的多線程測試用例。

 

#!/usr/bin/python
# -*- coding: utf-8 -*-

import threading


def synchronized(func):
    func.__lock__ = threading.Lock()

    def synced_func(*args, **kws):
        with func.__lock__:
            return func(*args, **kws)

    return synced_func


def Singleton(cls):
    instances = {}

    @synchronized
    def get_instance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return get_instance


def worker():
    single_test = test()
    print "id----> %s" % id(single_test)


@Singleton
class test():
    a = 1

if __name__ == "__main__":
    task_list = []
    for one in range(30):
        t = threading.Thread(target=worker)
        task_list.append(t)

    for one in task_list:
        one.start()

    for one in task_list:
        one.join()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM