2011-10-19 37 views
44

Cụ thể, tôi đang tìm hàng đợi chặn. Có một điều như vậy trong C++ 11? Nếu không, các lựa chọn khác của tôi là gì? Tôi thực sự không muốn đi xuống cấp thread nữa. Cách quá dễ bị lỗi.Có bất kỳ thùng chứa đồng thời nào trong C++ 11 không?

+2

+1, Thú vị Q.Scott Meyers đã hỏi điều này trong C++ 0x ngày [tại đây] (http://www.velocityreviews.com/forums/t732306-concurrent-containers.html) .Nó thật thú vị khi biết làm thế nào điều này đã thay đổi bài C + + 11. –

+0

Rất dễ dàng để biến hàng đợi chuẩn thành hàng đợi chặn sử dụng nguyên thủy –

Trả lời

32

According to Diego Dagum from Microsoft's Visual C++ Team:

Một câu hỏi tái phát (tốt, một trong rất nhiều) là về STL container và cho dù họ là chủ đề an toàn.

Lấy các từ của Stephan ở đây, thực tế là chúng không, không phải là lỗi mà là một tính năng: có mọi chức năng thành viên của mỗi container STL chứa khóa nội bộ sẽ tiêu diệt hiệu suất. Vì một thư viện có mục đích chung, có thể tái sử dụng cao, nó thực sự không phải là cung cấp tính chính xác: mức độ chính xác cho các khóa đặt là được xác định bởi những gì chương trình đang làm. Theo nghĩa đó, các chức năng của thành viên không có xu hướng chính xác như vậy.

The Parallel Patterns Library (PPL) bao gồm một số container cung cấp thread-safe quyền truy cập vào các yếu tố của họ:

  • Các concurrent_vector Class là một lớp chứa chuỗi cho phép truy cập ngẫu nhiên để bất kỳ yếu tố. Nó cho phép nối thêm đồng thời, truy cập phần tử, truy cập lặp và các hoạt động truyền tải lặp.
  • concurrent_queue Class là một lớp chứa thứ tự cho phép truy cập đầu tiên, đầu tiên vào các phần tử của nó. Nó cho phép một tập hợp hạn chế các hoạt động an toàn tương tranh, chẳng hạn như push và try_pop, để đặt tên một vài.

Một số mẫu here.

Cũng thú vị: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html.

+0

. nhưng vấn đề là - nó chỉ dành cho windows = ( –

1

Giao diện của các thùng chứa đơn giản không được thiết kế với mục tiêu này. Đối với các giao diện họ sử dụng, một khóa hiển thị cho khách hàng thực sự là cách duy nhất bạn có thể thực hiện điều này trong khi đảm bảo tính đúng đắn và hành vi có thể dự đoán được. Nó cũng sẽ vô cùng hiệu quả bởi vì số lượng mua lại sẽ rất cao (liên quan đến việc thực hiện tốt).

Giải pháp 1

đèo theo giá trị (nếu có).

Giải pháp 2

Tạo một tập hợp các đơn giản bolt-on hiện thực mà bạn có thể sử dụng để vượt qua container trong khi giữ một khóa phạm vi (xem xét nó giả C++):

template <typename TCollection> 
class t_locked_collection { 
public: 
    t_locked_collection(TCollection& inCollection, t_lock& lock) : collection(inCollection), d_lock(lock), d_nocopy() { 
    } 

    TCollection& collection; 
    // your convenience stuff 
private: 
    t_scope_lock d_lock; 
    t_nocopy d_nocopy; 
}; 

sau đó người gọi ghép nối khóa với bộ sưu tập và sau đó bạn cập nhật giao diện của mình để sử dụng (vượt qua) loại vùng chứa khi thích hợp. Nó chỉ là một phần mở rộng của lớp người nghèo.

Vùng chứa bị khóa này là một ví dụ đơn giản và có một vài biến thể khác.Đây là con đường tôi chọn vì nó thực sự cho phép bạn sử dụng mức độ chi tiết lý tưởng cho chương trình của bạn, mặc dù nó không minh bạch (cú pháp) như các phương thức bị khóa. Nó cũng tương đối dễ dàng để thích ứng với các chương trình hiện có. Ít nhất nó hoạt động theo cách có thể dự đoán được, không giống như các bộ sưu tập có khóa bên trong.

biến thể khác sẽ là:

template <typename TCollection> 
class t_lockable_collection { 
public: 
// ... 
private: 
    TCollection d_collection; 
    t_mutex d_mutex; 
}; 

// example: 
typedef t_lockable_collection<std::vector<int> > t_lockable_int_vector; 

... nơi một kiểu tương tự như t_locked_collection có thể được sử dụng để phơi bày bộ sưu tập bên dưới. Không ngụ ý rằng cách tiếp cận đó là dễ dàng, chỉ cần đánh lừa kháng cự.

+0

với "pass by value" bởi vì bạn có nghĩa là vượt qua các container hoàn chỉnh theo giá trị để tạo một bản sao và làm việc trên bản sao? Hoặc vượt qua các mục của container theo giá trị? – steffen

+0

@steffen chuyển các phần tử của container theo giá trị, xem xét giao diện mà nhiều thùng chứa, (** Solution 1 **) là một giải pháp tối ưu. Cách tiếp cận này cũng gần như chính xác, trừ khi bạn sẵn sàng viết – justin

8

C++ 11 không tự cung cấp các thùng chứa đồng thời. Tuy nhiên, có các tùy chọn thư viện. Bên cạnh PPL đã đề cập, đừng quên thư viện TBB của Intel.

Nó có đồng thời queue, hash_map, setvector triển khai. Nhưng nó không chỉ là một thư viện chứa an toàn cho luồng, nó còn đi kèm với phiên bản song song của các thuật toán chuẩn (for-loop, reduce, sort, ...).

Intel TBB website

+1

Bạn có thể cho tôi liên kết của bộ đồng thời không? – user

2

Tôi ngạc nhiên là không ai đề cập moodycamel::ConcurrentQueue. Chúng tôi đã sử dụng nó trong một thời gian và nó hoạt động rất tốt. Cụ thể là việc thực hiện nó không có khóa, tức là nó mang lại một tốc độ rất lớn. Các lý do khác để sử dụng nó (trích dẫn từ trang web chính thức):

Không có nhiều hàng đợi không khóa chính thức cho C++. Boost có một, nhưng nó bị giới hạn đối với các đối tượng với các toán tử gán tầm thường và các trình phá hủy tầm thường, chẳng hạn. Hàng đợi TBB của Intel không phải là không có khóa và cũng yêu cầu các nhà xây dựng tầm thường. Có rất nhiều tài liệu học tập thực hiện hàng đợi không có khóa trong C++, nhưng có thể sử dụng mã nguồn có thể sử dụng được và thậm chí nhiều thử nghiệm hơn nữa.

Một số điểm chuẩn và so sánh có sẵn here, herehere.

+0

Vấn đề với việc thực hiện moodycamel là nó không phải là FIFO (tức là thứ tự các phần tử xuất hiện không được đảm bảo giống như thứ tự của các yếu tố đẩy) vì vậy nó không phải là một giải pháp phổ quát. –

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