日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

聊聊 Python 中的同步原語,為什么有了 GIL 還需要同步原語

來源: 責編: 時間:2024-04-03 09:08:52 253觀看
導讀前言? 在前面的文章中我們介紹了 Python 中的全局解釋器鎖 GIL,我們知道 GIL 可以保證在多線程場景下同一時刻只有一個線程運行,但是并不能保證線程安全(所謂線程安全簡單來說就是程序在多線程環境中運行時,線程在交替運

前言

? 在前面的文章中我們介紹了 Python 中的全局解釋器鎖 GIL,我們知道 GIL 可以保證在多線程場景下同一時刻只有一個線程運行,但是并不能保證線程安全(所謂線程安全簡單來說就是程序在多線程環境中運行時,線程在交替運行時能正常的訪問共享資源,不會造成數據不一致或者死鎖,最后都能達到預期的結果),比如我們看下面的兩個例子:43R28資訊網——每日最新資訊28at.com

對 counter 進行累加

import threadingimport timecounter = 0temp_count = 0def increment():    global counter, temp_count    for _ in range(1000):        counter += 1        temp = temp_count        time.sleep(0.0001)        temp_count = temp + 1start = time.time()threads = []for _ in range(10):    t = threading.Thread(target=increment)    threads.append(t)    t.start()for t in threads:    t.join()end = time.time()print("Final counter value:", counter)print("Final temp_count value:", temp_count)print(f"總共耗時:{end - start}")# 運行結果Final counter value: 10000Final temp_count value: 1001總共耗時:0.5465419292449951

? 上面我們對 counter 做多線程累積時,盡管 counter += 1 是非原子操作,但是由于 CPU 執行太快,因此我們很難復現線程不安全的情況,因此我們使用 temp_count 寫法進行手動模擬。43R28資訊網——每日最新資訊28at.com

賬戶取款

import threadingclass BankAccount:    def __init__(self, balance):        self.balance = balance    def withdraw(self, amount):        if self.balance >= amount:            # 發生線程切換            self.balance -= amount            print(f"Withdrawal successful. Balance: {self.balance}")        else:            print("Insufficient funds")    def deposit(self, amount):        self.balance += amount        print(f"Deposit successful. Balance: {self.balance}")if __name__ == "__main__":    account = BankAccount(1000)    # 創建多個線程進行取款存款操作    threads = []    for _ in range(5):        t = threading.Thread(target=account.withdraw, args=(account, 200))        threads.append(t)        t.start()    for t in threads:        t.join()

? 上面的代碼同樣是線程不安全的,考慮這個場景,如果此時賬戶余額中剩余200,線程1執行完 self.balance >= amount 后切換到線程2,線程2正常取款200,然后切換回線程1,導致此時余額為-2200。43R28資訊網——每日最新資訊28at.com

使用同步原語保證線程安全

? 從上面的兩個案例中我們可以看出,GIL 并不能保證線程安全,我們需要使用同步原語來進行線程同步保證線程安全。43R28資訊網——每日最新資訊28at.com

locked、release 顯式獲取鎖和釋放鎖

? 在一些比較老的 python 代碼中,我們可以看到很多使用 locked、release 顯式獲取鎖和釋放鎖 的用法。43R28資訊網——每日最新資訊28at.com

import threadingclass BankAccount:    def __init__(self, balance):        self.balance = balance        self.lock = threading.Lock()    def withdraw(self, amount):        self.lock.locked()        if self.balance >= amount:            self.balance -= amount            print(f"Withdrawal successful. Balance: {self.balance}")        else:            print("Insufficient funds")        self.lock.release()    def deposit(self, amount):        self.lock.locked()        self.balance += amount        print(f"Deposit successful. Balance: {self.balance}")        self.lock.release()if __name__ == "__main__":    account = BankAccount(1000)    # 創建多個線程進行取款存款操作    threads = []    for _ in range(5):        t = threading.Thread(target=account.withdraw, args=(account, 200))        threads.append(t)        t.start()    for t in threads:        t.join()

使用 with 語句同步原理

? 相比于這種顯式調用的方法,with 語句更加優雅,也更不容易出錯,特別是程序員可能會忘記調用 release() 方法或者程序在獲得鎖之后產生異常這兩種情況(使用 with 語句可以保證在這兩種情況下仍能正確釋放鎖)。43R28資訊網——每日最新資訊28at.com

import threadingclass BankAccount:    def __init__(self, balance):        self.balance = balance        self.lock = threading.Lock()    def withdraw(self, amount):        with self.lock:            if self.balance >= amount:                self.balance -= amount                print(f"Withdrawal successful. Balance: {self.balance}")            else:                print("Insufficient funds")    def deposit(self, amount):        with self.lock:            self.balance += amount            print(f"Deposit successful. Balance: {self.balance}")if __name__ == "__main__":    account = BankAccount(1000)    # 創建多個線程進行取款存款操作    threads = []    for _ in range(5):        t = threading.Thread(target=account.withdraw, args=(account, 200))        threads.append(t)        t.start()    for t in threads:        t.join()

其它支持同步原語:RLock 和 Semaphore

RLock

? 一個 RLock (可重入鎖)可以被同一個線程多次獲取,主要用來實現基于監測對象模式的鎖定和同步。在使用這種鎖的情況下,當鎖被持有時,只有一個線程可以使用完整的函數或者類中的方法。43R28資訊網——每日最新資訊28at.com

import threadingclass SharedCounter:    '''    A counter object that can be shared by multiple threads.    '''    _lock = threading.RLock()    def __init__(self, initial_value = 0):        self._value = initial_value    def incr(self,delta=1):        '''        Increment the counter with locking        '''        with SharedCounter._lock:            self._value += delta    def decr(self,delta=1):        '''        Decrement the counter with locking        '''        with SharedCounter._lock:             self.incr(-delta)

? 在上邊這個例子中,沒有對每一個實例中的可變對象加鎖,取而代之的是一個被所有實例共享的類級鎖。這個鎖用來同步類方法,具體來說就是,這個鎖可以保證一次只有一個線程可以調用這個類方法。不過,與一個標準的鎖不同的是,已經持有這個鎖的方法在調用同樣使用這個鎖的方法時,無需再次獲取鎖。比如 decr 方法。 這種實現方式的一個特點是,無論這個類有多少個實例都只用一個鎖。因此在需要大量使用計數器的情況下內存效率更高。不過這樣做也有缺點,就是在程序中使用大量線程并頻繁更新計數器時會有爭用鎖的問題。43R28資訊網——每日最新資訊28at.com

Semaphore

? 信號量對象是一個建立在共享計數器基礎上的同步原語。如果計數器不為0,with 語句將計數器減1,線程被允許執行。with 語句執行結束后,計數器加1。如果計數器為0,線程將被阻塞,直到其他線程結束將計數器加1。43R28資訊網——每日最新資訊28at.com

import urllib.requestfrom threading import Semaphore# At most, five threads allowed to run at once_fetch_url_sema = Semaphore(5)def fetch_url(url):    with _fetch_url_sema:        return urllib.request.urlopen(url)

本文鏈接:http://m.www897cc.com/showinfo-26-81056-0.html聊聊 Python 中的同步原語,為什么有了 GIL 還需要同步原語

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 我們一起聊聊軟件架構伸縮性法則

下一篇: React 19 要來了!究竟帶來了哪些實用的特性呢?

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国产精品美腿一区在线看| 亚洲精品三级| 国产精品色午夜在线观看| 国产精品高潮视频| 国产日韩欧美在线一区| 一区在线电影| 夜夜嗨网站十八久久| 亚洲欧美日韩精品| 久久精品国产亚洲一区二区三区| 久久免费视频网站| 欧美激情第9页| 国产精品久久久久久久久搜平片| 国产色视频一区| 亚洲国产综合91精品麻豆| 91久久极品少妇xxxxⅹ软件| 中文一区在线| 久久激情综合| 欧美剧在线观看| 国产热re99久久6国产精品| 激情亚洲网站| 一区二区三区四区在线| 欧美中文字幕视频| 欧美日韩成人一区| 国产一区在线视频| 亚洲最快最全在线视频| 久久久久一区二区三区四区| 欧美午夜片在线观看| 在线成人免费观看| 亚洲欧美日韩天堂| 欧美黄色一级视频| 国产午夜精品麻豆| 亚洲色图自拍| 国产在线国偷精品产拍免费yy| 亚洲激情电影在线| 欧美一区二区三区久久精品| 欧美精品久久久久a| 国产亚洲综合性久久久影院| 一片黄亚洲嫩模| 蜜桃av综合| 国产欧美日韩精品一区| 日韩视频免费在线观看| 久久久久成人精品免费播放动漫| 欧美日韩免费观看一区=区三区| 狠狠色丁香婷婷综合影院| 亚洲在线观看免费| 欧美日本国产精品| 亚洲第一在线综合网站| 久久成人精品无人区| 欧美午夜三级| 日韩视频在线观看| 噜噜爱69成人精品| 国产欧美一区二区精品秋霞影院| 亚洲精品中文字| 久久综合伊人77777| 国产日韩精品一区观看| 亚洲一二三区精品| 欧美日韩精品系列| 亚洲国产精品久久91精品| 欧美专区亚洲专区| 国产精品人人爽人人做我的可爱 | 欧美成人官网二区| 黑人操亚洲美女惩罚| 性xx色xx综合久久久xx| 国产精品久久国产精麻豆99网站| 亚洲精品免费电影| 欧美sm极限捆绑bd| 国产色视频一区| 香蕉尹人综合在线观看| 欧美色道久久88综合亚洲精品| 在线电影国产精品| 久久精品夜夜夜夜久久| 国产精品人人爽人人做我的可爱 | 欧美一区永久视频免费观看| 欧美丝袜一区二区三区| 亚洲精品久久久久| 亚洲国产一区二区a毛片| 久久久国产精品一区二区中文| 国产亚洲欧美另类中文| 亚洲欧美国产va在线影院| 欧美日韩福利在线观看| 亚洲三级免费| 欧美阿v一级看视频| 亚洲大胆视频| 久久精品亚洲国产奇米99| 国产精品美女在线观看| 亚洲欧美日韩一区二区三区在线观看 | 国内精品久久国产| 一区二区欧美视频| 欧美午夜精品久久久久久孕妇| 最新中文字幕亚洲| 欧美成人综合| 亚洲美女黄色片| 欧美紧缚bdsm在线视频| 亚洲国产精品传媒在线观看| 免费成人av| 影音先锋亚洲视频| 美腿丝袜亚洲色图| 国内精品久久久久影院优| 久久精品视频99| 尤物九九久久国产精品的特点| 久久国产精品免费一区| 在线观看亚洲视频| 另类欧美日韩国产在线| 亚洲国产精品一区二区尤物区| 欧美成人69| 一本一本久久a久久精品牛牛影视| 欧美日韩在线视频一区| 亚洲一二三区在线| 国产精品久久久久久久久久久久久久 | 欧美精品 国产精品| 亚洲日本中文字幕免费在线不卡| 欧美日本中文| 99天天综合性| 国产欧美日韩视频在线观看| 欧美中文字幕不卡| 激情六月婷婷久久| 久久亚洲精品一区二区| 在线观看亚洲| 欧美日韩国产三级| 午夜精彩视频在线观看不卡| 国产精品美女诱惑| 久久视频国产精品免费视频在线| 一区二区三区在线视频播放| 欧美日韩99| 久久www成人_看片免费不卡| 黑人极品videos精品欧美裸| 葵司免费一区二区三区四区五区| 亚洲精品国产品国语在线app| 欧美精品在线免费| 亚洲欧美制服另类日韩| 国产色视频一区| 美乳少妇欧美精品| 一区二区欧美在线观看| 国产日本欧美一区二区三区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲天堂成人在线观看| 国产一区二区无遮挡| 久久综合中文| 一区二区三区四区五区在线| 国产无一区二区| 欧美成人免费观看| 香蕉久久夜色| **网站欧美大片在线观看| 国产精品久久久久国产精品日日| 久久精品国产99| 日韩天堂av| 国产日韩精品久久久| 欧美全黄视频| 久久精品国产久精国产一老狼| 精品成人国产| 国产精品色一区二区三区| 老色鬼精品视频在线观看播放| 一区二区三区|亚洲午夜| 欲香欲色天天天综合和网| 国产精品免费看| 欧美大片网址| 久久福利精品| 亚洲一区在线免费| 日韩午夜av| 亚洲国产欧美另类丝袜| 国产亚洲在线观看| 国产精品日韩欧美一区二区| 欧美精品一区二区三区高清aⅴ| 久久久999国产| 亚洲欧美国产视频| 日韩视频在线免费观看| 黄色一区二区三区四区| 国产乱理伦片在线观看夜一区| 欧美日韩国产一区二区| 欧美成人国产va精品日本一级| 久久精品视频亚洲| 欧美一区国产二区| 亚洲欧美国产精品专区久久| 一区二区高清在线| 亚洲美女视频| 亚洲日本aⅴ片在线观看香蕉| 精品51国产黑色丝袜高跟鞋| 国产伦精品一区二区三区高清版| 国产精品va在线| 欧美男人的天堂| 美女精品一区| 久久免费黄色| 久久久久久9| 久久精品国产一区二区电影 | 日韩一区二区精品| 亚洲国产精品成人va在线观看| 精品999日本| 韩国av一区二区三区在线观看| 国产婷婷色一区二区三区| 国产精品视频999| 国产精品久久激情| 欧美性大战久久久久久久蜜臀| 欧美人在线视频| 欧美日韩www| 欧美精品在线一区| 欧美成人免费网站| 欧美成在线观看| 欧美成人网在线| 欧美极品在线播放| 欧美理论片在线观看| 欧美激情精品久久久久久变态| 欧美第一黄色网| 欧美韩国日本综合| 欧美激情久久久久久|