boost::shared_mutex
hoặc std::shared_mutex
(C++ 17) có thể được sử dụng cho người viết đơn, truy cập nhiều đầu đọc. Là một bài tập giáo dục, tôi đã cùng nhau triển khai thực hiện đơn giản sử dụng spinlocking và có những hạn chế khác (ví dụ: chính sách công bằng), nhưng rõ ràng không được sử dụng trong các ứng dụng thực tế.C++ shared_mutex implementation
Ý tưởng là mutex giữ số tham chiếu bằng 0 nếu không có luồng nào giữ khóa. Nếu> 0, giá trị đại diện cho số lượng người đọc có quyền truy cập. Nếu -1, một người viết duy nhất có quyền truy cập.
Đây có phải là cách triển khai chính xác (đặc biệt với các thứ tự bộ nhớ tối thiểu, đã sử dụng) không có các cuộc đua dữ liệu?
#include <atomic>
class my_shared_mutex {
std::atomic<int> refcount{0};
public:
void lock() // write lock
{
int val;
do {
val = 0; // Can only take a write lock when refcount == 0
} while (!refcount.compare_exchange_weak(val, -1, std::memory_order_acquire));
// can memory_order_relaxed be used if only a single thread takes write locks ?
}
void unlock() // write unlock
{
refcount.store(0, std::memory_order_release);
}
void lock_shared() // read lock
{
int val;
do {
do {
val = refcount.load(std::memory_order_relaxed);
} while (val == -1); // spinning until the write lock is released
} while (!refcount.compare_exchange_weak(val, val+1, std::memory_order_acquire));
}
void unlock_shared() // read unlock
{
refcount.fetch_sub(1, std::memory_order_relaxed);
}
};
Tôi không chắc chắn về thứ tự bộ nhớ trong unlock_shared, nhưng lý do của tôi là nó không thực sự 'phát hành' bất cứ điều gì vì nó có quyền truy cập chỉ đọc và không thể thay đổi dữ liệu nó bảo vệ – LWimsey
@LWimsey: vâng, khó hơn để suy nghĩ về thứ tự tải hơn so với thứ tự lưu trữ, nhưng đó là một điều thực sự. Một tải sẽ trở thành trên toàn cầu có thể nhìn thấy tại thời điểm khi nó đọc dữ liệu từ bộ nhớ cache L1. (Bởi vì đó là khi nó tạo một bản sao từ bộ nhớ đệm toàn cục kết hợp vào lõi không theo thứ tự của một CPU đơn.) –