Rust程式語言的標準函式庫內建了三種可在不同執行緒間實現同步的機制,分別是原子(Atomic)型別、訊息傳遞(message passing)以及互斥鎖(Mutex)。這三種機制的應用方式差異很大,但在某些情況下原子型別和互斥鎖是可以替換使用的。那麼究竟原子型別和互斥鎖,哪個效能是比較好的呢?



先前已經有寫過原子型別的文章,還沒看過的讀者們可以先透過以下連結來閱讀:

https://magiclen.org/rust-atomic/

假設有個型別為u8的變數n,我們先來看看這行程式敘述:

n += 1;

以上程式可以讓變數n的值加1。如果要確保這個操作在同一時間只有一個執行緒會處理的話,可以用原子型別AtomicU8來作為變數n的型別,並將以上程式改寫成:

n.fetch_add(1, std::sync::atomic::Ordering::Relaxed);

或者也可以用某個互斥鎖來組成臨界區段(Critical Section):

let lock = mutex.lock().unwrap();
n += 1;
drop(lock)

既然在這個例子中,原子型別和互斥鎖都可以做到一樣的事,那麼誰的效能好呢?

效能實測

直接實際寫一段程式來測試運算效能吧!這段程式可以在GitHub上取得:

https://github.com/magiclen/rust-performance-measurement/blob/master/benches/atomic_mutex.rs

根據測試結果,使用原子型別的效能比用互斥鎖的效能還要好大概四倍吧!也就是說,如果要在同一個區塊進行超過四次的原子操作,儘量還是改用互斥鎖吧!