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()