在這個POC(概念證明)中,我們將探索Rust語言如何處理競爭條件,並將其與C ,一種廣泛使用的語言,但競爭的安全保障較少。
Rust 線路安全性:與 C 的比較執行緒安全:從 C 到 Rust 的資料競爭
指數執行緒用於將軟體任務分割為可以並發執行的子任務。透過使用線程,我們獲得了處理時間並更好地利用機器的資源,但這種競爭帶來了挑戰,例如競爭條件,這可能會產生數據的嚴重不一致。
執行緒是允許您同時處理任務的執行單元。我們可以將執行緒視為程式內獨立的執行流,如下圖所示:
此外,執行緒還可以用來實現並行性,即多個任務在不同的CPU核心上同時執行。這使得程式能夠更好地利用可用的硬件,加快獨立任務的執行速度。
C 中建立一個簡單的系統:
int saldo = 1000; void creditar(int valor) { int tmp_saldo = saldo; sleep(1); // Delay simulado saldo += tmp_saldo + valor; } void debitar(int valor) { int temp = saldo; sleep(1); // Delay simulado if (temp >= valor) { saldo = temp - valor; } } void* processar_transacao(void* arg) { int valor = *(int*)arg; if (valor > 0) { creditar(valor); } else { debitar(abs(valor)); } return NULL; } int main() { int transactions[] = {100, -50, 200, -150, 300, -200, 150, -100, 50, -50}; int num_transactions = sizeof(transactions) / sizeof(transactions[0]); pthread_t threads[num_transactions]; for (int i = 0; i < num_transactions; i++) { pthread_create(&threads[i], NULL, processar_transacao, &transactions[i]); // Cria uma thread para cada transação } for (int i = 0; i < num_transactions; i++) { pthread_join(threads[i], NULL); // Aguarda todas as threads terminarem } printf("Saldo final da conta: %d\n", saldo); return 0; }
多執行緒處理的環境時,我們所說的競爭條件可能會發生,當兩個執行緒存取並修改相同的值時,我們就會出現競爭條件。出現此問題的原因是,由於呼叫之間的競爭,無法保證每個執行緒中存取的值的同步。
多次執行此程式碼時,最終餘額會有所不同,因為執行緒同時存取和更改餘額。
int saldo = 1000; void creditar(int valor) { int tmp_saldo = saldo; sleep(1); // Delay simulado saldo += tmp_saldo + valor; } void debitar(int valor) { int temp = saldo; sleep(1); // Delay simulado if (temp >= valor) { saldo = temp - valor; } } void* processar_transacao(void* arg) { int valor = *(int*)arg; if (valor > 0) { creditar(valor); } else { debitar(abs(valor)); } return NULL; } int main() { int transactions[] = {100, -50, 200, -150, 300, -200, 150, -100, 50, -50}; int num_transactions = sizeof(transactions) / sizeof(transactions[0]); pthread_t threads[num_transactions]; for (int i = 0; i < num_transactions; i++) { pthread_create(&threads[i], NULL, processar_transacao, &transactions[i]); // Cria uma thread para cada transação } for (int i = 0; i < num_transactions; i++) { pthread_join(threads[i], NULL); // Aguarda todas as threads terminarem } printf("Saldo final da conta: %d\n", saldo); return 0; }
互斥體是一種同步原語,可確保一次只有一個執行緒可以存取共享資源。縮寫互斥體來自英文術語互斥,意思是「互斥」。
當一個執行緒取得互斥體時,任何其他嘗試取得相同互斥體的執行緒都會被掛起,直到第一個執行緒釋放互斥體。這可以防止兩個或多個進程(執行緒)同時存取共享資源。
int saldo = 1000; pthread_mutex_t saldo_mutex; // Mutex para proteger o saldo void creditar(int valor) { pthread_mutex_lock(&saldo_mutex); // Bloqueia o mutex int tmp_saldo = saldo; sleep(1); // Delay simulado saldo = tmp_saldo + valor; pthread_mutex_unlock(&saldo_mutex); // Libera o mutex } void debitar(int valor) { pthread_mutex_lock(&saldo_mutex); // Bloqueia o mutex int tmp_saldo = saldo; sleep(1); // Delay simulado if (tmp_saldo >= valor) { saldo = tmp_saldo - valor; } pthread_mutex_unlock(&saldo_mutex); // Libera o mutex }
將Rust 視為一種不存在於資料競賽中的語言並不高效,但我們可以理解結構 及其編譯器如何透過為記憶體和執行緒安全帶來出色的功能來做出貢獻。
Rust 使用 所有權、借用 和並發安全結構等功能,透過編譯時保證來對待競爭條件:
不使用 Arc 和 Mutex 結構
Rust’s rich type system and ownership model guarantee memory-safety and thread-safety — enabling you to eliminate many classes of bugs at compile-time.
Rust 不允許在沒有保護的情況下從多個線程直接存取可變資料(餘額)。
編譯器將產生錯誤,因為餘額在沒有安全機制的情況下被移動到多個執行緒(handle1 和 handle2)。
將顯示的錯誤訊息是:
fn main() { let mut saldo = 1000; // saldo mutável, mas sem proteção let handle1 = thread::spawn(move || { saldo += 100; // erro: `saldo` é movido para esta thread sem proteção }); let handle2 = thread::spawn(move || { saldo -= 50; // erro: `saldo` é movido para esta thread sem proteção }); handle1.join().unwrap(); handle2.join().unwrap(); }
使用 Mutex 和 Arc,我們能夠編譯並執行我們的程式碼,並解決了競爭條件問題。
error[E0382]: use of moved value: `saldo`
Mutex 和 RwLock 用來處理競爭條件,各自具有特定的優點:
互斥體:保證一個執行緒對資源的獨佔訪問,阻止對其他執行緒的訪問,直到該執行緒被釋放。它簡單而有效,但即使是讀取也會阻塞資源,從而在讀取密集的場景中效率較低。
RwLock:使用 .read() 允許多個同時讀取,並使用 .write() 限制獨佔寫入。它非常適合以讀取為主的場景,因為它透過允許讀取操作中的並行性來提高效能。
C 和 Rust 之間的比較突顯了解決競爭條件的不同方法。 C 需要注意避免競爭條件錯誤,而 Rust 除了所有權模型之外還透過 Mutex、RwLock 和 Arc 等工具在編譯時降低了這些風險。這不僅使程式碼更加安全,還透過避免無聲錯誤減少了程式設計師的心理負擔。
總之,Rust 將自己定位為開發競爭系統的絕佳選擇,提供安全性和可靠性。
以上是Rust 線路安全性:與 C 的比較。的詳細內容。更多資訊請關注PHP中文網其他相關文章!