2008-12-12 29 views
9

Làm thế nào để const (con trỏ, tham chiếu và chức năng thành viên) giúp an toàn luồng trong C++?An toàn chủ đề và `const`

+0

Nó không. Chỉ vì một tham chiếu đến một biến là const, không ngụ ý rằng không có tham chiếu không const nào cho biến đó. –

+0

@ChrisBecke Phải thừa nhận rằng, http://stackoverflow.com/questions/14127379/does-const-mean-thread-safe-in-c11 này là một câu hỏi tốt hơn nhiều, được hỏi với nhiều trở ngại hơn. Tôi nghĩ rằng các câu trả lời cho thấy rằng một glib 'nó không' là không đủ. –

Trả lời

6

Vấn đề chính với nhiều chủ đề là khả năng thay đổi. const hạn chế điều này, nhưng kể từ khi bạn có thể bỏ đi các const-ness, nó không phải là dễ dàng.

+5

Đúng, nhưng bạn cần phải làm thêm để tự chụp chân mình. –

+2

Tôi đồng ý và là một lập trình viên C# những ngày này tôi chắc chắn bỏ lỡ const & –

+3

Không có mã nào là lừa đảo, nhưng bạn phải bảo vệ chống lại Murphy, không chống lại Machiavelli. – Gorpik

14

Bất kỳ dữ liệu bất biến (có thể thay đổi) vốn dĩ là an toàn - không có rủi ro cho nhiều luồng đồng thời đọc cùng một dữ liệu chỉ đọc vì nó không bao giờ thay đổi!

Đánh dấu biến là const trong C++ làm cho chỉ đọc và do đó chỉ an toàn.

+0

Giả sử bạn không sử dụng bất cứ nơi nào có thể thay đổi bất cứ nơi nào ;-) –

+1

Và giả sử khởi tạo của nó là an toàn chỉ. – xtofl

+1

Khởi tạo thường là. Tại sao bạn chia sẻ một đối tượng chưa được khởi tạo đầy đủ? –

6

Chức năng thành viên const không được thay đổi trạng thái khiến cho việc gọi từ nhiều luồng cùng một lúc trở nên an toàn. Tuy nhiên thread an toàn không phải là mục đích của const và C++ cung cấp các từ khóa mutable và const_cast có nghĩa là const không thực sự đảm bảo an toàn thread và không nên được dựa vào cho mục đích này.

4

Chức năng Const không phải là chủ đề an toàn. Normaly, bạn có thể gọi các phương thức đối tượng const từ các luồng khác nhau đồng thời, nhưng nếu bạn gọi phương thức không const và const từ các luồng khác nhau, bạn sẽ nhận được điều kiện chủng tộc. Kiểm tra điều này:

class Foo 
{ 
    size_t size_; 
public: 
    ... 
    size_t get_size() const 
    { 
     return size_ 
    } 
}; 

class Bar 
{ 
    boost::shared_ptr<Foo> foo_; 
public: 
    //accessor 
    size_t get_size() const 
    { 
     size_t size = 0; 
     if (foo_) 
      size = foo_->size(); 
     return size; 
    } 
    //modifiers 
    void init() 
    { 
     foo_ = new Foo; 
    } 

    void clear() 
    { 
     foo_ = boost::shared_ptr<Foo>(); 
    } 
}; 

Nếu ai đó gọi phương thức init, sau đó gọi phương thức clear và get_size đồng thời sẽ gây ra vi phạm truy cập. Bạn phải sử dụng đọc viết thành ngữ khóa. Nhiều người truy cập có thể được gọi cùng một lúc và chỉ có thể gọi một trình sửa đổi cùng một lúc. dụ:

class Bar 
{ 
    boost::shared_ptr<Foo> foo_; 
    mutable tbb::spin_rw_mutex lock_; 
public: 
    //accessor 
    size_t get_size() const 
    { 
     size_t size = 0; 
     //lock modifiers 
     rw_mutex_type::scoped_lock lock(mutex, false); 
     if (foo_) 
      size = foo_->size(); 
     return size; 
    } 
    //modifiers 
    void init() 
    { 
     //lock accessor and modifiers 
     rw_mutex_type::scoped_lock lock(mutex, true); 
     foo_ = new Foo; 
    } 

    void clear() 
    { 
     //lock accessor and modifiers 
     rw_mutex_type::scoped_lock lock(mutex, true); 
     foo_ = boost::shared_ptr<Foo>(); 
    } 
}; 

TBB :: spin_rw_lock là một lớp mutex từ threading builing blocks library

+0

Thực tế: constness chỉ _helps_ xây dựng các ứng dụng an toàn cho luồng – xtofl

4

C++ const cho phép răng cưa không const như:

Foo myVar; 
const Foo* ptr1; 
Foo* ptr2; 

Vì điều này, const không cung cấp đảm bảo như tính bất biến của dữ liệu của bạn, ngay cả khi bạn không thực hiện bất kỳ thao tác truyền hoặc bất kỳ thứ gì để giải quyết nó. Nếu bạn truy cập myVar thông qua ptr1, bạn không thể thay đổi nó thông qua ptr1 (giả sử tôi có cú pháp đúng, đó là ý định.) Tuy nhiên, nó vẫn có thể thay đổi thông qua ptr2. Những gì bạn thực sự muốn là một cấu trúc bất biến riêng biệt. Điều này không tồn tại trong C++.

3

Const and thread safety là các khái niệm trực giao. Lấy một hàm const làm ví dụ: Một lớp có thể có cả hàm const và non-const, và một luồng có thể gọi một hàm không const để sửa đổi đối tượng tại cùng một thời điểm mà một luồng khác nằm trong hàm const của nó. . Trong trường hợp này, đánh dấu hàm const không cung cấp sự an toàn nào. Chủ đề an toàn chỉ đạt được với khóa hoặc nguyên gốc đồng bộ hóa khác.