Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Từ khóa volatile trong C++

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

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++

  1. Memory-mapped I/O (Embedded): Thanh ghi phần cứng
  2. Signal handler: Biến chia sẻ với handler (chỉ volatile sig_atomic_t an toàn)
  3. 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

Tối ưu hóaBình thườngvolatile
Cache registerCóKhông
Loại bỏ đọc/ghi dư thừaCóKhông
Reorder lệnhCóKhông (giữ thứ tự)
Đặc điểmvolatilestd::atomic
AtomicityKhôngCó
Memory orderingKhôngCó (sequential consistency mặc định)
Compiler reorderNgănNgăn
CPU reorderKhông ngănNgăn (memory fence)
Dùng choHardware, signal, setjmpThread 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