30/09/2018, 16:04

Volatile In C/C++ For Thread Safe

Một bài viết rất hay về cách sử dụng volatile modified để truy xuất biến từ nhiều thread an toàn, tránh trường hợp dồn đuổi (race condition)

http://collaboration.cmc.ec.gc.ca/science/rpn/biblio/ddj/Website/articles/CUJ/2001/cexp1902/alexandr/alexandr.htm

Nguyễn Minh Dũng viết 18:04 ngày 30/09/2018

Hix, bài dài quá, Huân có thể tóm tắt ngắn gọn tại sao dùng volatile có thể truy xuất biến từ nhiều thread an toàn không? Vì theo anh hiểu thì volatile chỉ đảm bảo compiler không optimize cái biến này thôi mà. Sao lại có liên quan đên threadsafe?

Tran Huan viết 18:04 ngày 30/09/2018

Dùng ví dụ trong bài:

class Gadget
{
public:
    void Wait()
    {
        while (!flag_)
        {
            Sleep(1000); // sleeps for 1000 milliseconds
        }
    }
    void Wakeup()
    {
        flag_ = true;
    }
    ...
private:
    bool flag_;
};

Trường hợp này không an toàn vì compiler có thể optimize bằng cách dùng register cho biến flag_ vì phát hiện hàm sleep sẽ không thay đổi biến flag_. Do đó nếu gọi Wakeup từ thread khác thì giá trị trong register vẫn không thay đổi mà chỉ thay đổi giá trị thật trong bộ nhớ. Làm thread chạy vĩnh viển

Nguyễn Minh Dũng viết 18:19 ngày 30/09/2018

À hay, cái này không để ý ha. Như trước giờ a toàn đề bool flag_; thôi. Vẫn chạy được là do may mắn, vì compiler hoàn toàn có thể optimize cái flag_ đi.

Nhưng có một điểm anh hơi nghi ngờ về cái ví dụ này, compiler chỉ optimize nếu nó không tìm thấy một phép gán mà trong đó flag_lvalue. Mà trong ví dụ này thì ít ra có hàm Wakeup có gán flag_ rồi. Nếu vậy thì compiler không được optimize chứ?

void Wakeup()
{
    flag_ = true;
}

Hay là compiler sẽ kiểm tra xem Wakeup có thực sự được gọi hay không? Nếu nó không tìm thấy được chỗ nào gọi hàm Wakeup (vì có thể gọi bằng signal hoặc vì lý do compiler cùi không tìm thấy được. Thì khi đó nó mới optimize?

Tran Huan viết 18:09 ngày 30/09/2018

Em nghĩ Unit để optimize của compiler trong trường hợp này là trong 1 function được call, vì nó không tính đến yếu tố multithread. Còn việc có dùng registry để cache biến flag_ không thì tùy trường hợp và tùy compiler. Để an toàn thì mình nên dùng nó để hạn chế lỗi race codition rất khó debug!

Bài liên quan
0