2015-06-17 17 views
7

Tôi đang tạo một chương trình đa luồng C++ sử dụng pthread (tiêu chuẩn C++ 98).Đồng bộ hóa chủ đề cho bản đồ C++

Tôi có std :: bản đồ mà nhiều chuỗi sẽ truy cập. Quyền truy cập sẽ thêm và xóa các phần tử, sử dụng tìm và cũng truy cập các phần tử bằng toán tử [].

Tôi hiểu rằng việc đọc bằng toán tử [] hoặc thậm chí sửa đổi các thành phần với nó là luồng an toàn, nhưng phần còn lại của các thao tác thì không.

Câu hỏi đầu tiên: tôi có hiểu chính xác điều này không?

Một số chủ đề sẽ chỉ truy cập các phần tử qua [], trong khi một số khác sẽ thực hiện một số thao tác khác. Rõ ràng tôi cần một số hình thức đồng bộ hóa thread.

Cách tôi thấy điều này sẽ hoạt động là: - Trong khi không có thao tác "ghi" đang được thực hiện trên bản đồ, tất cả các chuỗi đều có thể "đọc" từ đồng thời. - Khi một chủ đề muốn "ghi" vào bản đồ, nó sẽ đặt khóa để không có luồng nào bắt đầu bất kỳ thao tác "đọc" hoặc "ghi" nào, và sau đó nó sẽ đợi cho đến khi tất cả các thao tác "đọc" đã hoàn thành, tại thời điểm đó nó sẽ thực hiện thao tác và giải phóng khóa. - Sau khi khóa đã được giải phóng, tất cả các chuỗi sẽ có thể đọc tự do.

Câu hỏi chính là: Tôi có thể sử dụng phương pháp đồng bộ hóa chủ đề nào để đạt được hành vi này?

Tôi đã đọc về mutex, biến có điều kiện và semaphores, và theo như tôi có thể thấy họ sẽ không làm excatly những gì tôi cần. Tôi quen thuộc với mutex nhưng không phải với cond. biến hoặc semaphores.

Vấn đề chính mà tôi thấy là tôi cần một cách khóa luồng cho đến khi có điều gì đó xảy ra (thao tác ghi kết thúc) mà không có chủ đề nào sau đó khóa bất kỳ thứ gì. Ngoài ra tôi cần một cái gì đó giống như một semaphore ngược, mà khối trong khi truy cập là nhiều hơn 1 và sau đó thức dậy khi nó là 0 (tức là không có hoạt động đọc đang được thực hiện).

Xin cảm ơn trước.

P.S. Đó là bài viết đầu tiên của tôi. Vui lòng cho biết nếu tôi đang làm điều gì sai!

+1

Bạn chỉ cần một trình soạn thảo độc giả? –

+1

Bạn cần khóa RW, hãy thử [ví dụ này.] (Http://stackoverflow.com/questions/989795/example-for-boost-shared-mutex-multiple-reads-one-write) – gbjbaanb

+0

Bài đăng đầu tiên tốt. Chắc chắn bạn không thể sử dụng [C++ 11] (http://en.cppreference.com/w/cpp/thread)? Nó sẽ đơn giản hóa mã của bạn và làm cho nó dễ dàng hơn. Tùy thuộc vào bản chất của các thành phần thùng chứa, bạn có thể không cần các tính năng luồng nặng hơn. Có lẽ [sync] (http://en.cppreference.com/w/cpp/atomic) nguyên thủy sẽ là đủ. –

Trả lời

6

Tôi hiểu rằng việc đọc bằng cách sử dụng toán tử [] hoặc thậm chí sửa đổi các thành phần với nó là luồng an toàn, nhưng phần còn lại của thao tác thì không.

Tôi có hiểu chính xác điều này không?

Vâng, những gì bạn đã nói không đúng. độc giả đồng thời có thể sử dụng để truy cập []hiện yếu tố, hoặc sử dụng const chức năng khác (như find, size() ...) một cách an toàn nếu không có đồng thời không const hoạt động như erase hoặc insert đột biến các map<>. Các chủ đề đồng thời có thể sửa đổi các phần tử khác nhau, nhưng nếu một chủ đề sửa đổi một phần tử, bạn phải đồng bộ hóa trước khi một chuỗi khác cố truy cập hoặc sửa đổi thêm phần tử cụ thể đó.

Khi một chủ đề muốn "ghi" vào bản đồ, nó sẽ đặt khóa để không bắt đầu bất kỳ thao tác "đọc" hoặc "ghi" nào và sau đó phải đợi cho đến khi tất cả các thao tác "đọc" đã hoàn tất , tại thời điểm đó nó sẽ thực hiện các hoạt động và phát hành các ổ khóa. - Sau khi khóa đã được giải phóng, tất cả các luồng sẽ có thể đọc tự do.

Đó không phải là khá cách nó hoạt động ... cho các nhà văn để có thể 'đợi cho đến khi tất cả 'đọc' các hoạt động đã hoàn thành', người đọc (s) cần phải có được một khóa. Các nhà văn sau đó chờ đợi cho cùng một khóa được phát hành, và có được nó để hạn chế độc giả khác hoặc nhà văn cho đến khi họ đã hoàn thành cập nhật của họ và phát hành nó.

tôi có thể sử dụng phương pháp đồng bộ hóa chủ đề nào để đạt được hành vi này?

Một mutex thực sự phù hợp, mặc dù bạn thường nhận được hiệu suất cao hơn từ khóa đọc của người đọc (cho phép người đọc đồng thời, một số cũng ưu tiên người viết đang chờ đọc thêm). POSIX đề liên quan đến chức năng bao gồm: pthread_rwlock_rdlock, pthread_rwlock_wrlock, pthread_rwlock_unlock vv ..

Để đối chiếu hai cách tiếp cận, với các độc giả và tác giả sử dụng một mutex bạn nhận được serialization một cái gì đó như thế này:

THREAD ACTION 
reader1 pthread_mutex_lock(the_mutex) returns having acquired lock, and 
     thread starts reading data 
reader2 pthread_mutex_lock(the_mutex) "hangs", as blocked by reader1 
writer1 pthread_mutex_lock(the_mutex) hangs, as blocked by reader1 
reader1 pthread_mutex_unlock(the_mutex) -> releases lock 
NOTE: some systems guarantee reader2 will unblock before writer1, some don't 
reader2 blocked pthread_mutex_lock(the_mutex) returns having acquired lock, 
     and thread starts reading data 
reader1 pthread_mutex_lock(the_mutex) hangs, as blocked by reader2 
reader2 pthread_mutex_unlock(the_mutex) -> releases lock  
writer1 blocked pthread_mutex_lock(the_mutex) returns having acquired lock, 
     and thread starts writing and/or reading data 
writer1 pthread_mutex_unlock(the_mutex) -> releases lock  
reader1 blocked pthread_mutex_lock(the_mutex) returns having acquired lock, 
     and thread starts reading data 
...etc... 

Với đọc-ghi khóa, nó có thể giống như thế này (thông báo hai người đọc đầu tiên chạy đồng thời):

THREAD ACTION 
reader1 pthread_rwlock_rdlock(the_rwlock) returns having acquired lock, and 
     thread starts reading data 
reader2 pthread_rwlock_rdlock(the_rwlock) returns having acquired lock, and 
     thread starts reading data 
writer1 pthread_rwlock_wrlock(the_rwlock) hangs, as blocked by reader1/2 
reader1 pthread_rwlock_unlock(the_rwlock) -> releases lock 
reader1 pthread_rwlock_rwlock(the_rwlock) hangs, as pending writer 
reader2 pthread_rwlock_unlock(the_rwlock) -> releases lock  
writer1 blocked pthread_rwlock_wrlock(the_rwlock) returns having acquired lock, 
     and thread starts writing and/or reading data 
writer1 pthread_rwlock_unlock(the_rwlock) -> releases lock  
reader1 blocked pthread_rwlock_rwlock(the_rwlock) returns having acquired lock, 
     and thread starts reading data 
...etc... 
+0

khóa đọc/ghi thực sự là những gì tôi cần. Không biết về họ! Cảm ơn. – Dan

+1

Tùy thuộc vào tình huống, đa đồng thời có thể là một lựa chọn, chẳng hạn như có thể được thực hiện bằng cách đặt 'shared_ptr' vào bản đồ chứ không phải là một đối tượng. Người đọc sao chép các con trỏ được chia sẻ và một nhà văn thay thế nguyên tử nó bằng một cái khác. Vì vậy, các đối tượng được đọc sống lâu hơn trong bản đồ cho đến khi chúng không còn cần thiết nữa. Lưu ý rằng việc sao chép xung quanh các con trỏ được chia sẻ không chính xác là "miễn phí", điều này có thể nhanh hơn hoặc chậm hơn so với khóa người đọc, tùy thuộc vào việc bạn làm. – Damon

+0

@Damon: đề xuất tốt - có thể thuộc về một câu trả lời riêng biệt hoặc nhận xét trực tiếp dưới câu hỏi ...? Tùy thuộc vào bạn. Chúc mừng. –

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