2012-01-28 31 views
29

Tôi có nhiều chuỗi cùng lúc gọi push_back() trên đối tượng được chia sẻ là std::vector. Có phải an toàn là sợi an toàn std::vector? Hay tôi có cần phải tự mình thực hiện cơ chế để làm cho nó an toàn không?
Tôi muốn tránh thực hiện thêm "khóa và giải phóng" hoạt động vì tôi là người dùng thư viện chứ không phải nhà thiết kế thư viện. Tôi hy vọng sẽ tìm kiếm các giải pháp an toàn thread hiện có cho vectơ. Làm thế nào về boost::vector, vừa được giới thiệu từ tăng 1.48.0 trở đi. Nó có an toàn không?Là std :: vector hoặc boost :: vector thread safe?

+0

Điều này phải là một số. Nhưng, không, không có thùng chứa tiêu chuẩn nào an toàn chỉ. – smparkes

+0

Xem thêm: http://stackoverflow.com/questions/1999122/how-to-define-threadsafe – ergosys

+0

Không hoàn toàn là lừa đảo, nhưng có liên quan: http://stackoverflow.com/questions/1099513/threadsafe-vector-class- for-c – ergosys

Trả lời

44

Chuẩn C++ giúp đảm bảo luồng nhất định cho tất cả các lớp trong thư viện C++ chuẩn. Những đảm bảo này có thể không phải là những gì bạn mong đợi, nhưng đối với tất cả các lớp thư viện C++ chuẩn, một số đảm bảo an toàn chủ đề được thực hiện. Tuy nhiên, hãy đảm bảo rằng bạn đã đọc các đảm bảo được thực hiện, vì việc đảm bảo luồng của các thùng chứa C++ chuẩn thường không phù hợp với những gì bạn muốn. Đối với một số lớp khác nhau, thường mạnh hơn, đảm bảo được thực hiện và câu trả lời dưới đây đặc biệt áp dụng cho các thùng chứa. Các container chủ yếu có đảm bảo thread-an toàn sau:

  1. có thể có nhiều độc giả đồng thời cùng một container
  2. nếu có một nhà văn, sẽ không có nhiều tác giả và không có độc giả

Đây thường không phải là những gì mọi người muốn đảm bảo an toàn luồng nhưng rất hợp lý cho giao diện của các thùng chứa tiêu chuẩn: chúng được dự định sử dụng hiệu quả trong trường hợp không có nhiều chuỗi truy cập. Việc thêm bất kỳ loại khóa nào cho các phương thức của chúng sẽ can thiệp vào điều này. Ngoài ra, giao diện của các thùng chứa không thực sự hữu ích cho bất kỳ hình thức khóa nội bộ nào: thường có nhiều phương thức được sử dụng và các truy cập phụ thuộc vào kết quả của các truy cập trước đó. Ví dụ: sau khi đã kiểm tra rằng vùng chứa không phải là empty(), một phần tử có thể được truy cập. Tuy nhiên, với khóa bên trong không có gì đảm bảo rằng đối tượng vẫn nằm trong vùng chứa khi nó thực sự được truy cập.

Để đáp ứng các yêu cầu đưa ra các đảm bảo trên, bạn có thể sẽ phải sử dụng một số hình thức khóa ngoài cho các thùng chứa được truy cập đồng thời. Tôi không biết về các thùng chứa tăng nhưng nếu họ có một giao diện tương tự như của các thùng chứa tiêu chuẩn tôi sẽ nghi ngờ rằng họ có chính xác cùng một đảm bảo.

Các bảo lãnh và yêu cầu được đưa ra trong 17.6.4.10 [res.on.objects] đoạn 1:

Hành vi của một chương trình là undefined nếu các cuộc gọi đến các hàm thư viện chuẩn từ chủ đề khác nhau có thể đưa ra một dữ liệu cuộc đua. Các điều kiện theo đó điều này có thể xảy ra được quy định trong 17.6.5.9. [Lưu ý: Sửa đổi một đối tượng của một kiểu thư viện chuẩn được chia sẻ giữa các luồng rủi ro hành vi không xác định trừ khi các đối tượng thuộc loại đó được xác định rõ ràng là có thể chia sẻ mà không có cuộc đua dữ liệu hoặc người dùng cung cấp cơ chế khóa. —endnote]

... và 17.6.5.9 [res.on.data.races]. Phần này về cơ bản chi tiết các mô tả chính thức hơn trong không.

+0

Gọi là reentrancy :) – vines

+2

Nó sẽ [reentrancy] (http://en.wikipedia.org/wiki/Reentrancy_%28computing%29) nếu nó chỉ có chức năng. Tuy nhiên, có các đối tượng liên quan được đảm bảo không được sửa đổi bởi các hoạt động đọc. Ngoài ra, reentrancy đề cập đến các tính năng được gọi đệ quy có thể gọi trong các chương trình đơn luồng. –

+0

Bởi "người đọc" và "nhà văn", bạn đang nói về cấu trúc của thùng chứa, và không ghi vào các đối tượng bên trong, đúng không? Ví dụ, viết cho 3 phần tử vector khác nhau và đọc từ một phần tư từ mười chuỗi khác, sẽ được cho phép tất cả cùng một lúc, miễn là không có phần tử chèn hoặc xóa nào. Các quy tắc về tính hợp lệ của trình lặp có vẻ có liên quan ở đây. –

25

Tôi có nhiều chủ đề đồng thời gọi push_back() trên đối tượng được chia sẻ của std :: vector. Là std :: vector thread an toàn?

Đây là không an toàn.

Hoặc tôi có cần tự mình thực hiện cơ chế để làm cho chuỗi đó an toàn không?

Có.

Tôi muốn tránh thực hiện thêm công việc "khóa và giải phóng" vì tôi là người dùng thư viện chứ không phải nhà thiết kế thư viện. Tôi hy vọng sẽ tìm kiếm các giải pháp an toàn thread hiện có cho vectơ.

Vâng, giao diện của véc tơ không phải là tối ưu để sử dụng đồng thời. Nó là tốt nếu khách hàng có quyền truy cập vào một khóa, nhưng đối với giao diện để khóa trừu tượng cho mỗi hoạt động - không. Trong thực tế, giao diện của vector không thể đảm bảo an toàn luồng mà không có khóa ngoài (giả sử bạn cần các thao tác cũng biến đổi).

Cách tăng :: vectơ, được giới thiệu từ tăng 1.48.0 trở đi. Nó có an toàn không? nhà nước

Documents:

//! boost::container::vector is similar to std::vector but it's compatible 
//! with shared memory and memory mapped files. 
8

Tôi có nhiều luồng đồng thời kêu gọi push_back() trên một đối tượng chia sẻ của std :: vector. ... Tôi hy vọng tìm kiếm các giải pháp an toàn chủ đề hiện có cho vectơ.

Hãy xem concurrent_vector trong Intel's TBB. Nói đúng ra, nó hoàn toàn khác với std::vector nội bộ và không hoàn toàn tương thích với API, nhưng vẫn có thể phù hợp. Bạn có thể tìm thấy một số chi tiết về thiết kế và chức năng của nó in the blogs of TBB developers.

Các vấn đề liên quan