---
# System prepended metadata

title: mutex、atomic、volatile

---

# mutex、atomic、volatile
這是我問ai的問題跟他的回答，可隨意看看:
https://grok.com/share/bGVnYWN5_98e6784c-3a01-44a7-a1f2-29d50432244b

## atomic
它本身保證原子性跟記憶體可見性，對於簡單的type:比如int、bool等等可用它，也只有這些簡單的type可用atomic(因為它內部實踐的限制，所以atomic只能用於簡單的type)。效能比用mutex高。
當然也可用mutex去鎖住一個int或bool等等。
![image](https://hackmd.io/_uploads/BkGnfjnA1g.png)

[std::atomic - cppreference.com](https://en.cppreference.com/w/cpp/atomic/atomic)
![image](https://hackmd.io/_uploads/ry4aPo3AJg.png)
https://grok.com/share/bGVnYWN5_a589fe1c-d945-46d7-948b-9f1c756cbfa1

## mutex
mutex本身保證記憶體可見性跟互斥存取，對於複雜的數據結構會用他去做保護。
![image](https://hackmd.io/_uploads/HkY4fi3AJx.png)
[std::mutex::unlock - cppreference.com](https://en.cppreference.com/w/cpp/thread/mutex/unlock)
![image](https://hackmd.io/_uploads/BkOgvj30yl.png)
https://grok.com/share/bGVnYWN5_5e46bdd2-fa20-4836-b5cf-5ba1ad50d1ff

## volatile使用場景
volatile對於我們用c++開發應用程式的人用不到。

在開發嵌入式系統跟硬體打交道的情況下。
開發嵌入式系統通常會用c語言寫，並且嵌入式系統的cpu通常是單核的，也就是只會有單一條thread。
會有一種使用情況是你需要透過一個特定的記憶體位置(比如宣告一個global變數)去控制硬體，同時硬體也可以改寫這個變數在記憶體的值。

例子 : 你在code內宣告一個bool light = false;去表示一個led的開關(硬體)是開還是關。你可以透過code去控制它。並且led硬體本身也有一個實體開關，當我們用手去把他打開或關閉時，led開關會發信號去改變這個開關對應到的記憶體那個變數的值。

由於我們寫的code在編譯時，為了效能考量，編譯器可能會對特定很頻繁被存取的變數放到cpu快取，而不是每次要用到該變數時，都去記憶體存取該變數。那此時就會產生該變數在快取的值跟在記憶體的值不一致的情況。假設編譯器優化該變數到快取，並且此時light = false;但此時led開關被打開，light = true。就發生資料(該變數的值)不一致的情況了。

補充 : 
1. 硬體只能存取記憶體的值，不能存取快取換cpu暫存器的值。這有個詞叫做 ["Memory-Mapped I/O"  ](https://grok.com/share/bGVnYWN5_ca324d96-136b-42c4-883e-b2ab701b5317)
2. 可看這篇 : [【C/C++面试必备】详解C/C++中volatile关键字_c++ volatile-CSDN博客](https://blog.csdn.net/qq_44918090/article/details/125749268)
3. 對多核心嵌入式系統，如果有個變數會同時被多個thread存取以及被硬體存取，ai說會直接用c11(c的標準庫不是c++的標準庫)的<stdatomic.h>的atomic，它隱含volatile語義並同時保證atomic跟memory可見性。![image](https://hackmd.io/_uploads/HyB6xs3Ckg.png)

