volatile trong C++ có ngữ nghĩa tương tự C: báo cho compiler biết biến có thể thay đổi bởi nguồn bên ngoài không nhìn thấy được (hardware, signal handler, thread khác - tuy không khuyến khích cho thread).
Cú pháp
volatile int a;
int volatile a; // Tương đương
volatile int* ptr; // Con trỏ TO dữ liệu volatile
int* volatile ptr; // Con trỏ VOLATILE (ít dùng)
volatile int* volatile ptr; // Cả hai
Tác động tối ưu hóa
| Tối ưu hóa | Bình thường | volatile |
| Cache register | Có | Không |
| Loại bỏ đọc/ghi dư thừa | Có | Không |
| Reorder lệnh | Có | Không (giữ thứ tự) |
Ví dụ: Không volatile vs Có volatile
// Không volatile - compiler có thể tối ưu vòng lặp thành vô tận
int flag = 0;
void wait() {
while (flag == 0) { } // Compiler thấy flag không đổi trong loop -> while(true)
}
// Có volatile - compiler buộc đọc bộ nhớ mỗi lần
volatile int flag = 0;
void wait() {
while (flag == 0) { } // Luôn kiểm tra địa chỉ flag
}
Khi nào dùng volatile trong C++
- Memory-mapped I/O (Embedded): Thanh ghi phần cứng
- Signal handler: Biến chia sẻ với handler (chỉ
volatile sig_atomic_t an toàn)
setjmp/longjmp: Biến cục bộ thay đổi sau longjmp
volatile KHÔNG dùng cho Multi-threading!
volatile ≠ thread-safe. Không đảm bảo atomicity, memory ordering, visibility giữa threads.
Ví dụ SAI (volatile cho thread)
volatile int counter = 0; // SAI cho multi-thread!
void increment() {
for (int i = 0; i < 1000000; ++i) counter++;
}
// Race condition: counter++ không atomic, reorder vẫn xảy ra
C++11: Đúng - std::atomic
#include <atomic>
#include <thread>
std::atomic<int> counter{0}; // Thread-safe, atomic
void increment() {
for (int i = 0; i < 1000000; ++i) counter++;
// Hoặc: counter.fetch_add(1, std::memory_order_relaxed);
}
int main() {
std::thread t1(increment), t2(increment);
t1.join(); t2.join();
std::cout << counter; // Đúng 2000000
}
So sánh volatile vs atomic
| Đặc điểm | volatile | std::atomic |
| Atomicity | Không | Có |
| Memory ordering | Không | Có (sequential consistency mặc định) |
| Compiler reorder | Ngăn | Ngăn |
| CPU reorder | Không ngăn | Ngăn (memory fence) |
| Dùng cho | Hardware, signal, setjmp | Thread communication |
Tóm tắt
volatile`: Ngăn compiler tối ưu hóa truy cập bộ nhớ
- Dùng cho: Hardware register, signal handler, setjmp/longjmp
- KHÔNG dùng cho đồng bộ thread (dùng
std::atomic, mutex)
- C++20:
std::atomic_ref cho atomic operations trên non-atomic object