python中的原子操作簡介

深入理解Python中的原子操作

在現代編程中,多線程是提高程序執行效率的常用技術。然而,當多個線程并發執行時,如何確保數據的一致性和操作的正確性成為了一個關鍵問題。原子操作(Atomic Operation)便是解決這一問題的重要概念。本文將詳細解釋什么是原子操作,并通過具體示例幫助讀者更好地理解這一概念。同時,我們還將探討與原子操作相關的其他技術,如線程安全、死鎖(Deadlock)以及Python中的其他同步機制。

什么是原子操作?

原子操作是指一個不可分割的操作,即這個操作在執行的過程中不會被其他操作打斷或干擾。在計算機科學中,原子性(Atomicity)意味著操作要么全部完成,要么全部不完成,沒有中間狀態。在多線程編程中,原子操作確保了在執行該操作時,其他線程無法訪問或修改共享數據,從而避免了競爭條件(Race Condition)和數據不一致問題。

Python中的原子操作

在Python中,某些操作是原子的,這些操作通常包括對簡單數據類型(如整數和浮點數)的基本運算和對單個對象屬性或列表元素的訪問。需要注意的是,本文討論的是CPython解釋器,因為不同的Python解釋器(如PyPy、Jython等)可能對原子操作有不同的實現。

整數和浮點數的簡單操作

在CPython中,對簡單的整數和浮點數的操作,如加減乘除,是原子的。例如:

x = 1
x += 1  # 這個操作在CPython中是原子的

上面的代碼中,x += 1是一個原子操作,因為在執行這個操作時,不會有其他線程插入或打斷。

單個屬性訪問和賦值

讀取和寫入對象的單個屬性也是原子的。例如:

class Counter:def __init__(self):self.count = 0counter = Counter()
counter.count += 1  # 這個操作在CPython中是原子的

在上面的代碼中,counter.count += 1是一個原子操作,因為對單個屬性的讀取和寫入不會被其他線程干擾。

單個列表元素的訪問和賦值

讀取和寫入列表的單個元素也是原子的。例如:

my_list = [1, 2, 3]
my_list[0] = 4  # 這個操作在CPython中是原子的

在上面的代碼中,my_list[0] = 4是一個原子操作,因為對單個列表元素的訪問和賦值不會被其他線程干擾。

需要注意的地方

盡管某些操作在CPython中是原子的,但并不是所有的操作都是原子的。對于復合數據結構的操作(如列表、字典的多個元素訪問或修改),通常不是原子的。這種情況下,需要使用鎖(Lock)來確保操作的原子性。

使用鎖確保原子性

鎖是一種用于控制多個線程對共享資源的訪問的同步機制。通過鎖,可以確保某些代碼塊在任意時刻只能由一個線程執行,從而實現操作的原子性。下面是一個簡單的示例,演示如何使用鎖來確保操作的原子性:

import threadingclass Counter:def __init__(self):self.count = 0self.lock = threading.Lock()def increment(self):with self.lock:self.count += 1  # 在鎖的保護下,這個操作是原子的counter = Counter()def worker():for _ in range(1000):counter.increment()threads = []
for _ in range(10):thread = threading.Thread(target=worker)thread.start()threads.append(thread)for thread in threads:thread.join()print(counter.count)  # 結果應該是10000

在這個例子中,increment方法在加鎖的情況下執行self.count += 1操作,從而確保該操作是原子的,不會被其他線程打斷。

線程安全和其他同步機制

除了鎖,Python還提供了其他幾種用于確保線程安全的同步機制,如條件變量(Condition Variable)、信號量(Semaphore)和事件(Event)。

條件變量

條件變量用于在線程之間進行復雜的同步,常用于生產者-消費者問題。例如:

import threadingcondition = threading.Condition()
queue = []def producer():with condition:queue.append(1)condition.notify()  # 通知消費者def consumer():with condition:while not queue:condition.wait()  # 等待生產者item = queue.pop(0)producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)
producer_thread.start()
consumer_thread.start()
producer_thread.join()
consumer_thread.join()

信號量

信號量用于控制對共享資源的訪問,如限制同時訪問某資源的線程數量。例如:

import threadingsemaphore = threading.Semaphore(3)def worker():with semaphore:print("Accessing shared resource")threads = []
for _ in range(5):thread = threading.Thread(target=worker)thread.start()threads.append(thread)for thread in threads:thread.join()

事件

事件用于線程間通信,使一個線程等待另一個線程的事件發生。例如:

import threadingevent = threading.Event()def setter():event.set()  # 觸發事件def waiter():event.wait()  # 等待事件觸發print("Event triggered")setter_thread = threading.Thread(target=setter)
waiter_thread = threading.Thread(target=waiter)
waiter_thread.start()
setter_thread.start()
setter_thread.join()
waiter_thread.join()

死鎖及其預防

在多線程編程中,死鎖是一個常見問題,指兩個或多個線程因互相等待對方釋放資源而陷入無限等待的狀態。為了預防死鎖,可以遵循以下策略:

  1. 資源分配順序:確保所有線程按照相同的順序請求資源。
  2. 嘗試鎖(Try Lock):使用嘗試獲取鎖的方法,如果無法獲取則放棄,以避免無限等待。
  3. 超時機制:為鎖設置超時時間,超過時間則釋放鎖并采取相應措施。

預防死鎖示例

使用嘗試鎖預防死鎖的示例:

import threadinglock1 = threading.Lock()
lock2 = threading.Lock()def worker1():while True:if lock1.acquire(timeout=1):if lock2.acquire(timeout=1):print("Worker1 acquired both locks")lock2.release()lock1.release()breakdef worker2():while True:if lock2.acquire(timeout=1):if lock1.acquire(timeout=1):print("Worker2 acquired both locks")lock1.release()lock2.release()breakthread1 = threading.Thread(target=worker1)
thread2 = threading.Thread(target=worker2)
thread1.start()
thread2.start()
thread1.join()
thread2.join()

總結

原子操作在多線程編程中是確保數據一致性和避免競爭條件的重要概念。盡管Python中某些簡單的操作是原子的,但對于更復雜的操作,通常需要使用鎖等同步機制來確保原子性。除此之外,理解線程安全、同步機制和死鎖預防,對于編寫健壯的多線程程序至關重要。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41855.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41855.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41855.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

責任鏈模式(大話設計模式)C/C++版本

責任鏈模式 C #include <iostream> #include <memory>using namespace std; // 請求類 struct Request {std::string requestType; // 請求類型int number; // 該請求類型的數量std::string requestContent; // 請求內容 };// 抽象經理類 clas…

MySQL學習記錄 —— ?? CentOS7.9環境下的MySQL8.4 安裝和配置

文章目錄 1、安裝和配置2、MySQL 包位置3、主要程序介紹 本篇開始在之前mysql博客的基礎上繼續延伸&#xff0c;適合有一定基礎的mysql使用者閱讀 環境 &#xff1a;CentOS 7.9 root 用戶&#xff0c;MySQL 8.4 1、安裝和配置 看一下當前系統版本 cat /etc/redhat-release應當…

前端重點之:Vue+websocket通信詳細用法和websocket心跳機制的使用,websocket斷開實時監測,websocket實時通信

今年年初找工作,好多gou面試官總喜歡問關于websocket通信的使用方式,此次又用到了,在此做個總結:主要包含websocket的具體使用方法,和重點:(心跳機制的使用),就是主要是前端實時監測websocket是否有斷連和數據的處理 在前端開發中,WebSocket 是一種常見的技術,用于…

淺談序列化及文本格式

序列化及文本格式 需求背景 軟件項目在開發過程中&#xff0c;將大量初始化配置項在一定程度上保存在配置文件中。肯定有很多人有疑問&#xff0c;為什么不將這些信息放在軟件內存中。開機時與用戶交互進行確認&#xff1f;這肯定是一個好想法&#xff0c;但是如果配置太多或…

眾所周知沃爾瑪1P是怎么運營?

??沃爾瑪的1P模式&#xff0c;即第一方供應商模式&#xff0c;是其獨特的采購策略。在這種模式下&#xff0c;供應商先將商品賣給沃爾瑪&#xff0c;由沃爾瑪負責庫存管理和銷售。沃爾瑪通過強大的采購和物流能力控制庫存&#xff0c;確保商品品質&#xff0c;為客戶提供更加…

FPGA問題

fpga 問題 第一道坎&#xff0c;安裝軟件&#xff1b;沒有注冊&#xff0c;無法產生sop文件&#xff0c;無法下載 沒有相應的庫的quartus ii版本&#xff0c;需要另下載 第二道坎&#xff0c;模擬器的下載&#xff0c;安裝&#xff1b; 第三道&#xff0c;verilog 語法&#x…

deepspeed huggingface傳入參數 optimizer和lr_scheduler測試

Trainer中 首先&#xff1a; WarmupDecayLR --lr_scheduler_type linear WarmupLR --lr_scheduler_type constant_with_warmup 1 TrainArgument不傳lr_scheduler_type、optim&#xff0c;warmup_steps15 ds config文件中定義如下&#xff1a; 注意&#xff1a;如果不在Trai…

LangChain(四)工具調用的底層原理!給大模型按上雙手吧!(新手向)

背景 經過前面三篇的內容&#xff0c;我想大家對于大模型的構建、Langchain的優勢、Chain的構建有了相當程度的理解&#xff08;雖然只是最簡單的示例&#xff0c;但是足夠有代表性&#xff09;。 后續Chain的使用將會更加豐富多彩&#xff0c;您會了解Langchain開發的大模型…

14-31 劍和詩人5 - 使用 AirLLM 和分層推理在單個 4GB GPU 上運行 LLama 3 70B

利用分層推理實現大模型語言(LLM) 大型語言模型 (LLM) 領域最近取得了顯著進展&#xff0c;LLaMa 3 70B 等模型突破了之前認為可能實現的極限。然而&#xff0c;這些模型的龐大規模給其部署和實際使用帶來了巨大挑戰&#xff0c;尤其是在資源受限的設備上&#xff0c;例如內存…

怎么壓縮pdf文件的大小?減小PDF文件大小的四種方法

怎么壓縮pdf文件的大小&#xff1f;文件大小不僅影響傳輸速度&#xff0c;還可能涉及存儲空間的管理。當處理大型PDF文件時&#xff0c;可能會面臨電子郵件附件限制或云存儲容量不足的問題。此外&#xff0c;過大的文件在瀏覽和加載時也會導致延遲&#xff0c;影響閱讀體驗。這…

3款自己電腦就可以運行AI LLM的項目

AnythingLLM、LocalGPT和PrivateGPT都是與大語言模型&#xff08;LLM&#xff09;相關的項目&#xff0c;它們允許用戶在本地環境中與文檔進行交互&#xff0c;但它們在實現方式和特點上存在一些差異。AnythingLLM使用Pinecone和ChromaDB來處理矢量嵌入&#xff0c;并使用OpenA…

【C語言】return 關鍵字詳解

在C語言中&#xff0c;return是一個關鍵字&#xff0c;用于從函數中返回值或者結束函數的執行。它是函數的重要組成部分&#xff0c;負責將函數的計算結果返回給調用者&#xff0c;并可以提前終止函數的執行。 主要用途和原理&#xff1a; 返回值給調用者&#xff1a; 當函數執…

mysql數據庫創建用戶并授權某個庫的所有權限

這個就直接上語句吧&#xff01;只是注意要用管理員帳號執行&#xff0c;比如root去執行。 -- 創建新用戶&#xff08;替換new_user為您的用戶名&#xff0c;password為您的密碼&#xff09; CREATE USER new_user% IDENTIFIED BY password; -- 授予權限&#xff08;替換data…

社交媒體數據分析:賦能企業營銷策略的利器

在這個數字化時代&#xff0c;社交媒體不僅是品牌與消費者互動的舞臺&#xff0c;更是企業洞察市場趨勢、優化營銷策略的金礦。本文將探討如何利用社交媒體數據分析賦能企業營銷&#xff0c;通過實戰案例與技巧分享&#xff0c;揭示這把“利器”如何幫助企業精準定位目標受眾、…

【論文閱讀】-- Visual Traffic Jam Analysis Based on Trajectory Data

基于軌跡數據的可視化交通擁堵分析 摘要1 引言2 相關工作2.1 交通事件檢測2.2 交通可視化2.3 傳播圖可視化 3 概述3.1 設計要求3.2 輸入數據說明3.3 交通擁堵數據模型3.4 工作流程 4 預處理4.1 路網處理4.2 GPS數據清理4.3 地圖匹配4.4 道路速度計算4.5 交通擁堵檢測4.6 傳播圖…

架構面試-場景題-單點登錄(SSO)怎么實現的

文章目錄 概述基于Cookie基于Token(OAuth, JWT)集中式認證服務 (CAS, SAML)分布式Session:輕型目錄訪問協議&#xff08;LDAP&#xff09;OAuth 2.0/OIDCKerberos 概述 單點登錄&#xff08;Single Sign-On&#xff0c;簡稱SSO&#xff09;是一種身份驗證機制&#xff0c;允許…

掌握【Python異常處理】:打造健壯代碼的現代編程指南

目錄 ?編輯 1. 什么是異常&#xff1f; 知識點 示例 小李的理解 2. 常見的內置異常類型 知識點 示例 小李的理解 3. 異常機制的意義 知識點 示例 小李的理解 4. 如何處理異常 知識點 示例 小李的理解 5. 拋出異常 知識點 示例 小李的理解 6. Python內置…

Springboot整合Jsch-Sftp

背景 開發一個基于jsch的sftp工具類&#xff0c;方便在以后的項目中使用。寫代碼的過程記錄下來&#xff0c;作為備忘錄。。。 Maven依賴 springboot依賴 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-par…

codeforces 1633A

文章目錄 1. 題目鏈接2. 題目代碼正確代碼錯誤代碼 3. 題目總結 1. 題目鏈接 Div. 7 2. 題目代碼 正確代碼 #include<iostream> using namespace std; int main(){int testCase;cin >> testCase;while(testCase --){int ingeter;cin >> ingeter;if(!(inget…

SpringBoot彩蛋之定制啟動畫面

寫在前面 在日常開發中&#xff0c;我們經常會看到各種各樣的啟動畫面。例如以下幾種 ① spring項目啟動畫面 ② mybatisplus啟動畫面 ③若依項目啟動畫面 還有很多各式各樣好看的啟動畫面&#xff0c;那么怎么定制這些啟動畫面呢&#xff1f; 一、小試牛刀 ① 新建一個Spr…