日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

print python 如何加锁_深度解密Python单例模式

發布時間:2025/3/20 python 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 print python 如何加锁_深度解密Python单例模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關代碼已經上傳至Github:Python_Development_Interview,大家可以收藏專題-Python的設計模式:解密+實戰,之后會持續更新相關的設計模式。

1. 認識單例模式

  • 認識單例模式
  • 1 單例模式含義
  • 2 單例模式優點
  • 3 單例模式缺點
  • 4 單例模式應用

2. Python實現單例模式

  • Python實現單例模式
  • 1 多種實現方法
  • 2 實例分析

3. 總結

  • 總結

認識單例模式

1.1 單例模式含義

例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利于我們協調系統整體的行為。比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然后服務進程中的其他對象再通過這個單例對象獲取這些配置信息。這種方式簡化了在復雜環境下的配置管理。

實現單例模式的思路是:一個類能返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態方法,通常使用getInstance這個名稱);當我們調用這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就創建該類的實例并將實例的引用賦予該類保持的引用;同時我們還將該類的構造函數定義為私有方法,這樣其他處的代碼就無法通過調用該類的構造函數來實例化該類的對象,只有通過該類提供的靜態方法來得到該類的唯一實例。

單例模式在多線程的應用場合下必須小心使用。如果當唯一實例尚未創建時,有兩個線程同時調用創建方法,那么它們同時沒有檢測到唯一實例的存在,從而同時各自創建了一個實例,這樣就有兩個實例被構造出來,從而違反了單例模式中實例唯一的原則。 解決這個問題的辦法是為指示類是否已經實例化的變量提供一個互斥鎖(雖然這樣會降低效率)。

1.2 單例模式優點

單例模式的優點: 1、由于單例模式要求在全局內只有一個實例,因而可以節省比較多的內存空間; 2、全局只有一個接入點,可以更好地進行數據同步控制,避免多重占用; 3、單例可長駐內存,減少系統開銷。

1.3 單例模式缺點

單例模式的缺點 1、單例模式的擴展是比較困難的; 2、賦于了單例以太多的職責,某種程度上違反單一職責原則(六大原則后面會講到); 3、單例模式是并發協作軟件模塊中需要最先完成的,因而其不利于測試; 4、單例模式在某種情況下會導致“資源瓶頸”。

1.4 單例模式應用

單例模式的應用舉例: 1、生成全局惟一的序列號; 2、訪問全局復用的惟一資源,如磁盤、總線等; 3、單個對象占用的資源過多,如數據庫等; 4、系統全局統一管理,如Windows下的Task Manager; 5、網站計數器。

Python實現單例模式

2.1 多種實現方法

2.1.1.使用模塊

其實,Python 的模塊就是天然的單例模式,因為模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。因此,我們只需把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了。如果我們真的想要一個單例類,可以考慮這樣做:

singleton_by_module.py

class Singleton(object):def foo(self):pass singleton = Singleton()

將上面的代碼保存在文件singleton_by_module.py中,要使用時,直接在其他文件中導入此文件中的對象,這個對象即是單例模式的對象test_singleton_by_module.py

from singleton_by_module import Singletont = Singleton()

這樣我們一旦調用到singleton_by_module.py就會產生一個singleton_by_module.pyc,以后我們每次調用都會直接引用這里面的代碼。

2.1.2.使用裝飾器

singleton_by_decorator.py

def Singleton(cls):_instance = {}count = 0def _singleton(*args, **kargs):nonlocal countif cls not in _instance:print(f"count: {count}: {cls.__name__} not init")_instance[cls] = cls(*args, **kargs)else:print(f"count: {count}: {cls.__name__} alreay init")count+=1return _instance[cls]return _singleton@Singleton class A(object):a = 1def __init__(self, x=0):self.x = xa1 = A(2) a2 = A(3)print(f"a1 id: {id(a1)}, a1 value: {a1.x}") print(f"a2 id: {id(a2)}, a2 value: {a2.x}")### output count: 0: A not init count: 1: A alreay init a1 id: 140536039677232, a1 value: 2 a2 id: 140536039677232, a2 value: 2

根據上面的運行情況,我們可以發現,當a1被創建后調用的是正常的產生實例的過程,當a2被創建的時候,由于之前實例已經被存儲下來,所以直接引用了a1的實例,所以他們的id是一樣的,也就是他們引用了同一個內存實例。

2.1.3.使用類

singleton_by_class.py

class Singleton:def __init__(self):pass@classmethoddef instance(cls, *args, **kwargs):if not hasattr(Singleton, "_instance"):Singleton._instance = Singleton(*args, **kwargs)return Singleton._instancea1 = Singleton.instance() a2 = Singleton.instance()print(f"a1 id: {id(a1)}") print(f"a2 id: {id(a2)}")### output a1 id: 140419818871776 a2 id: 140419818871776

一般情況,大家以為這樣就完成了單例模式,但是這樣當使用多線程時會存在問題

singleton_by_class_mutli_threading.py

class Singleton(object):def __init__(self):pass@classmethoddef instance(cls, *args, **kwargs):if not hasattr(Singleton, "_instance"):Singleton._instance = Singleton(*args, **kwargs)return Singleton._instanceimport threadingdef task(arg):obj = Singleton.instance()print(obj)for i in range(10):t = threading.Thread(target=task,args=[i,])t.start()

程序執行后,打印結果如下:

<__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0>

看起來也沒有問題,那是因為執行速度過快,如果在init方法中有一些IO操作,就會發現問題了,下面我們通過time.sleep模擬

我們在上面init方法中加入以下代碼:

singleton_by_class_mutli_threading_sleep.py

def __init__(self):import timetime.sleep(1)

重新執行程序后,結果如下

<__main__.Singleton object at 0x034A3410> <__main__.Singleton object at 0x034BB990> <__main__.Singleton object at 0x034BB910> <__main__.Singleton object at 0x034ADED0> <__main__.Singleton object at 0x034E6BD0> <__main__.Singleton object at 0x034E6C10> <__main__.Singleton object at 0x034E6B90> <__main__.Singleton object at 0x034BBA30> <__main__.Singleton object at 0x034F6B90> <__main__.Singleton object at 0x034E6A90>

問題出現了!按照以上方式創建的單例,無法支持多線程

解決辦法:加鎖!未加鎖部分并發執行,加鎖部分串行執行,速度降低,但是保證了數據安全

singleton_by_class_mutli_threading_lock.py

import time import threading class Singleton:_instance_lock = threading.Lock()def __init__(self):time.sleep(1)@classmethoddef instance(cls, *args, **kwargs):with Singleton._instance_lock:if not hasattr(Singleton, "_instance"):Singleton._instance = Singleton(*args, **kwargs)return Singleton._instancedef task(arg):obj = Singleton.instance()print(obj) for i in range(10):t = threading.Thread(target=task,args=[i,])t.start() time.sleep(20) obj = Singleton.instance() print(obj)

打印結果如下:

<__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110>

這樣就差不多了,但是還是有一點小問題,就是當程序執行時,執行了time.sleep(20)后,下面實例化對象時,此時已經是單例模式了,但我們還是加了鎖,這樣不太好,再進行一些優化,把intance方法,改成下面的這樣就行:

@classmethoddef instance(cls, *args, **kwargs):if not hasattr(Singleton, "_instance"):with Singleton._instance_lock:if not hasattr(Singleton, "_instance"):Singleton._instance = Singleton(*args, **kwargs)return Singleton._instance

這樣,一個可以支持多線程的單例模式就完成了

singleton_by_class_mutli_threading_safe.py

import time import threading class Singleton:_instance_lock = threading.Lock()def __init__(self):time.sleep(1)@classmethoddef instance(cls, *args, **kwargs):if not hasattr(Singleton, "_instance"):with Singleton._instance_lock:if not hasattr(Singleton, "_instance"):Singleton._instance = Singleton(*args, **kwargs)return Singleton._instancedef task(arg):obj = Singleton.instance()print(obj) for i in range(10):t = threading.Thread(target=task,args=[i,])t.start() time.sleep(20) obj = Singleton.instance() print(obj)完整代碼

這種方式實現的單例模式,使用時會有限制,以后實例化必須通過 obj = Singleton.instance()

如果用 obj=Singleton() ,這種方式得到的不是單例

2.1.4基于new方法實現(推薦使用,方便)

通過上面例子,我們可以知道,當我們實現單例時,為了保證線程安全需要在內部加入鎖

我們知道,當我們實例化一個對象時,是先執行了類的new方法(我們沒寫時,默認調用type.new),實例化對象;然后再執行類的init方法,對這個對象進行初始化,所有我們可以基于這個,實現單例模式

singleton_by_new.py

import threading class Singleton:_instance_lock = threading.Lock()def __init__(self):passdef __new__(cls, *args, **kwargs):if not hasattr(Singleton, "_instance"):with Singleton._instance_lock:if not hasattr(Singleton, "_instance"):Singleton._instance = super(Singleton,cls).__new__(cls,*args, **kwargs)return Singleton._instanceobj1 = Singleton() obj2 = Singleton() print(obj1,obj2)def task(arg):obj = Singleton()print(obj)for i in range(10):t = threading.Thread(target=task,args=[i,])t.start()

打印結果如下:

<__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0>

采用這種方式的單例模式,以后實例化對象時,和平時實例化對象的方法一樣 obj = Singleton()

2.1.5.基于metaclass方式實現

相關知識

""" 1.類由type創建,創建類時,type的init方法自動執行,類() 執行type的call方法(類的new方法,類的init方法) 2.對象由類創建,創建對象時,類的init方法自動執行,對象()執行類的call方法 """class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):passobj = Foo() # 執行type的 __call__ 方法,調用 Foo類(是type的對象)的 __new__方法,用于創建對象,然后調用 Foo類(是type的對象)的 __init__方法,用于對對象初始化。obj() # 執行Foo的 __call__ 方法

元類的使用metaclass_ex.py

class SingletonType(type):def __init__(self,*args,**kwargs):super(SingletonType,self).__init__(*args,**kwargs)def __call__(cls, *args, **kwargs): # 這里的cls,即Foo類print('cls',cls)obj = cls.__new__(cls,*args, **kwargs)cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj)return objclass Foo(metaclass=SingletonType): # 指定創建Foo的type為SingletonTypedef __init__(self,name):self.name = namedef __new__(cls, *args, **kwargs):return object.__new__(cls)obj = Foo('xx')

實現單例模式

singleton_by_metaclass.py

import threadingclass SingletonType(type):_instance_lock = threading.Lock()def __call__(cls, *args, **kwargs):if not hasattr(cls, "_instance"):with SingletonType._instance_lock:if not hasattr(cls, "_instance"):cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)return cls._instanceclass Foo(metaclass=SingletonType):def __init__(self,name):self.name = nameobj1 = Foo('name') obj2 = Foo('name') print(obj1,obj2)

2.2 實例分析

總線是計算機各種功能部件或者設備之間傳送數據、控制信號等信息的公共通信解決方案之一?,F假設有如下場景:某中央處理器(CPU)通過某種協議總線與一個信號燈相連,信號燈有64種顏色可以設置,中央處理器上運行著三個線程,都可以對這個信號燈進行控制,并且可以獨立設置該信號燈的顏色。抽象掉協議細節(用打印表示),如何實現線程對信號等的控制邏輯。 加線程鎖進行控制,無疑是最先想到的方法,但各個線程對鎖的控制,無疑加大了模塊之間的耦合。下面,我們就用設計模式中的單例模式,來解決這個問題。

代碼如下:

import threading import time #這里使用方法__new__來實現單例模式 class Singleton(object):#抽象單例def __new__(cls, *args, **kw):if not hasattr(cls, '_instance'):orig = super(Singleton, cls)cls._instance = orig.__new__(cls, *args, **kw)return cls._instance #總線 class Bus(Singleton):lock = threading.RLock()def sendData(self,data):self.lock.acquire()time.sleep(3)print "Sending Signal Data...",dataself.lock.release() #線程對象,為更加說明單例的含義,這里將Bus對象實例化寫在了run里 class VisitEntity(threading.Thread):my_bus=""name=""def getName(self):return self.namedef setName(self, name):self.name=namedef run(self):self.my_bus=Bus()self.my_bus.sendData(self.name)if __name__=="__main__":for i in range(3):print "Entity %d begin to run..."%imy_entity=VisitEntity()my_entity.setName("Entity_"+str(i))my_entity.start()

運行結果如下: Entity 0 begin to run... Entity 1 begin to run... Entity 2 begin to run... Sending Signal Data... Entity_0 Sending Signal Data... Entity_1 Sending Signal Data... Entity_2 在程序運行過程中,三個線程同時運行(運行結果的前三行先很快打印出來),而后分別占用總線資源(后三行每隔3秒打印一行)。雖然看上去總線Bus被實例化了三次,但實際上在內存里只有一個實例。

總結

因為單例模式在設計模式中算是最基礎且最簡單的一個模式,因此在一般初級面試的時候,面試官都會通過這個問題來考察,一個很重要的原因是單例模式實現方法多種且優化的方式也有很多,所以也很能考察應聘者的水平,所以,大家要好好學這個最基礎的設計模式啊!另外,在Java中單例模式常說的飽漢餓漢模式,其實和Python中的利用__new__和利用class來創建是一樣的,也就是在什么時候創建實例的區別。

總結

以上是生活随笔為你收集整理的print python 如何加锁_深度解密Python单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天堂av√ | 欧美精品国产动漫 | 欧美精品免费看 | 一区二区三区视频免费 | 国产一区二区自拍 | 黑人性视频 | 亚洲中文在线一区 | 逼逼av | 欧美xxxxbbb| 亚洲精品国产乱伦 | 俄罗斯精品一区二区三区 | 女同性做爰三级 | 日日鲁鲁鲁夜夜爽爽狠狠视频97 | 豆花视频在线播放 | 伊人成人在线观看 | 中文字幕伦理 | 四虎在线播放 | 欧美aa在线观看 | 国产国语老龄妇女a片 | 一本一道av无码中文字幕 | 精品福利电影 | 九九香蕉视频 | 水蜜桃av无码 | 国产性生活网站 | 使劲插视频 | 日韩黄片一区二区 | 国产精品ⅴa有声小说 | 成人精品视频在线 | caoporn视频在线| 欧美日韩国产第一页 | 性久久久久久久久久久 | 亚洲无人区码一码二码三码 | 国产成a人亚洲精v品无码 | 日韩在线观看一区 | 精品丰满人妻无套内射 | 欧美中文字幕一区二区三区 | 亚洲成人免费在线视频 | 九一成人网 | 欧美色综合天天久久综合精品 | 欧美成性色 | 免费在线观看你懂的 | 三点尽露的大尺度国产 | 岛国av免费在线 | 污视频网站在线观看 | 三上悠亚在线一区 | 深爱激情久久 | 视频区小说区 | 99国产在线播放 | 国内精品嫩模av私拍在线观看 | 另类天堂av| 色综合av综合无码综合网站 | 综合久久99| 欧美经典一区二区三区 | 麻豆观看 | 亚洲中文字幕一区在线 | 图书馆的女友在线观看 | 亚洲一区二区三区在线观看视频 | 日韩欧美中文字幕在线视频 | 久久精品色 | 国语播放老妇呻吟对白 | 欧美成人综合色 | 欧美日韩国产91 | 国产黄色免费大片 | 四虎影院一区 | 成人午夜又粗又硬又大 | 欧美精品亚洲一区 | 天堂av最新网址 | 香蕉福利 | 亚洲欧美中文日韩在线v日本 | 国产婷婷在线视频 | 日本日皮视频 | 在线无| 色www国产亚洲阿娇 自拍一区在线 | 欧美一级欧美三级在线观看 | 台湾男男gay做爽爽的视频 | 青娱乐导航 | 九九视频在线免费观看 | 在线日韩av | 动漫精品一区 | 亚洲熟乱 | 黑人玩弄人妻一区二 | 理论片大全免费理伦片 | 国产视频精品自拍 | 日b免费视频 | 波多野结衣视频一区二区 | 黑丝啪啪 | 伊人99在线 | 中国一极毛片 | 黄色一及毛片 | 日韩欧美高清在线视频 | 亚洲伦理影院 | 永久免费未满蜜桃 | 欧美老少做受xxxx高潮 | 国产精品桃色 | 午夜爱爱网站 | 激情五月五月婷婷 | 丁香激情网 | 精品国产18久久久久久 | 肉肉视频在线观看 |