Я ищу хороший фиксатор чтения/записи на С++. У нас есть случай использования одного редкого автора и многих частых читателей, и мы хотели бы его оптимизировать. Предпочтительно, я хотел бы использовать кросс-платформенное решение, однако только один из Windows был бы приемлемым.
Записи чтения/записи в С++
Ответ 1
В более новых версиях boost:: thread есть блокировки чтения/записи (1.35.0 и более поздние версии, по-видимому, предыдущие версии работали неправильно).
У них есть имена shared_lock
, unique_lock
и upgrade_lock
и работать с shared_mutex
.
Ответ 2
Используя стандартные предварительно протестированные, готовые вещи всегда хороши (например, Boost как другой ответ предложил), но это то, что не так сложно построить самостоятельно. Здесь небольшая небольшая реализация, извлеченная из моего проекта:
#include <pthread.h>
struct rwlock {
pthread_mutex_t lock;
pthread_cond_t read, write;
unsigned readers, writers, read_waiters, write_waiters;
};
void reader_lock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
if (self->writers || self->write_waiters) {
self->read_waiters++;
do pthread_cond_wait(&self->read, &self->lock);
while (self->writers || self->write_waiters);
self->read_waiters--;
}
self->readers++;
pthread_mutex_unlock(&self->lock);
}
void reader_unlock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
self->readers--;
if (self->write_waiters)
pthread_cond_signal(&self->write);
pthread_mutex_unlock(&self->lock);
}
void writer_lock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
if (self->readers || self->writers) {
self->write_waiters++;
do pthread_cond_wait(&self->write, &self->lock);
while (self->readers || self->writers);
self->write_waiters--;
}
self->writers = 1;
pthread_mutex_unlock(&self->lock);
}
void writer_unlock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
self->writers = 0;
if (self->write_waiters)
pthread_cond_signal(&self->write);
else if (self->read_waiters)
pthread_cond_broadcast(&self->read);
pthread_mutex_unlock(&self->lock);
}
void rwlock_init(struct rwlock *self) {
self->readers = self->writers = self->read_waiters = self->write_waiters = 0;
pthread_mutex_init(&self->lock, NULL);
pthread_cond_init(&self->read, NULL);
pthread_cond_init(&self->write, NULL);
}
pthreads
не является Windows-родным, но общая идея здесь. Эта реализация немного предвзята к писателям (орда писателей может голодать читателям бесконечно); просто измените writer_unlock
, если вы хотите, чтобы баланс был наоборот.
Да, это C, а не С++. Перевод - упражнение, оставленное читателю.
Изменить
Грег Роджерс отметил, что стандарт POSIX указывает pthread_rwlock_*
. Это не поможет, если у вас нет pthreads
, но это заставило меня вспомнить: Pthreads-w32 должен работать! Вместо того, чтобы портировать этот код на pthreads
для вашего собственного использования, просто используйте Pthreads-w32 в Windows и native pthreads
везде.
Ответ 3
Начиная с C++ 17 (VS2015) вы можете использовать стандарт:
#include <shared_mutex>
typedef std::shared_mutex Lock;
typedef std::unique_lock< Lock > WriteLock;
typedef std::shared_lock< Lock > ReadLock;
Lock myLock;
void ReadFunction()
{
ReadLock r_lock(myLock);
//Do reader stuff
}
void WriteFunction()
{
WriteLock w_lock(myLock);
//Do writer stuff
}
Для более старых версий и стандартов компилятора вы можете использовать boost для создания блокировки чтения-записи:
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
typedef boost::shared_lock< Lock > ReadLock;
Ответ 4
Независимо от того, что вы решите использовать, сравните свою рабочую нагрузку с простыми замками, поскольку блокировки чтения/записи имеют тенденцию быть на 3-40 раз медленнее, чем простой мьютекс, когда нет никаких утверждений.
Вот некоторая ссылка
Ответ 5
Изменить: ссылка на журнал MSDN недоступна. Статья CodeProject теперь доступна на https://www.codeproject.com/Articles/32685/Testing-reader-writer-locks и суммирует ее довольно красиво. Также я нашел новую ссылку MSDN о Составные объекты синхронизации.
Существует статья статьи о блокировщиках считывателя-писателя на MSDN, в которой представлены некоторые из них. Он также вводит Slim reader/writer lock, примитив синхронизации ядра, представленный с Vista. Там также статья CodeProject о сравнении различных реализаций (включая статьи MSDN).
Ответ 6
С++ 17 поддерживает std::shared_mutex
. Поддерживается в MSVC++ 2015 и 2017.
Ответ 7
Блоки Intel Thread Building также предоставляют пару вариантов rw_lock:
http://www.threadingbuildingblocks.org/
У них есть spin_rw_mutex для очень коротких периодов соперничества и queueing_rw_mutex для более длительных периодов раздора. Первый может использоваться в особенно чувствительном к производительности коде. Последний более сопоставим по производительности с тем, что обеспечивается Boost.Thread или напрямую с использованием pthreads. Но профиль, чтобы убедиться, какой из них является выигрышем для ваших шаблонов доступа.
Ответ 8
Я могу рекомендовать ACE library, которая предоставляет множество механизмов блокировки и переносится на различные платформы.
В зависимости от граничных условий вашей проблемы вы можете найти следующие классы:
-
ACE_RW_Process_Mutex
-
ACE_Write_Guard
иACE_Read_Guard
-
ACE_Condition
Ответ 9
Boost.Thread с тех пор, как релиз 1.35.0 уже поддерживает блокировки чтения-записи. Хорошая вещь в этом заключается в том, что реализация очень кросс-платформенная, рецензируемая, и на самом деле эталонная реализация для предстоящего стандарта С++ 0x.
Ответ 10
http://www.codeproject.com/KB/threads/ReaderWriterLock.aspx
Вот хорошая и легкая реализация, подходящая для большинства задач.
Ответ 11
Множественный читатель, класс блокировки синхронизации с одним писателем для Win32 от Glenn Slayde
Ответ 12
Вы можете скопировать Sun отлично ReentrantReadWriteLock. Он включает в себя такие функции, как необязательная справедливость, понижение рейтинга и, конечно, повторное размещение.
Да, это в Java, но вы можете легко прочитать и перенести его на С++, даже если вы не знаете Java. Документация, с которой я связан, содержит все поведенческие свойства этой реализации, поэтому вы можете убедиться, что она делает то, что вы хотите.
Если ничего другого, это руководство.