Блокировка чтения / записи в C++



Я ищу хороший замок для чтения / записи в C++. У нас есть случай использования одного нечастого писателя и многих частых читателей, и мы хотели бы оптимизировать для этого. Предпочтительно я хотел бы кросс-платформенное решение, однако Windows только один будет приемлемым.

1022   12  

12 ответов:

новые версии boost:: thread есть блокировки чтения/записи (1.35.0 и позже, по-видимому, предыдущие версии не работали правильно).

у них есть фамилии shared_lock,unique_lock и upgrade_lock и работы в shared_mutex.

использование стандартных предварительно протестированных, предварительно построенных материалов всегда хорошо (например, 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-native, но общая идея здесь. Эта реализация слегка смещена в сторону писателей (Орда писателей может голодать читателей бесконечно); просто измените writer_unlock Если вы предпочитаете баланс будет наоборот.

Да, это C, а не c++. Перевод-это упражнение, оставленное читателю.

Edit

Грег Роджерс отметил, что стандарт POSIX указывает pthread_rwlock_*. Это не поможет, если у вас нет pthreads, но это заставило меня вспомнить:Pthreads-w32 должно работать! Вместо переноса этого кода в non -pthreads для вашего собственного использования, просто используйте Pthreads-w32 на Windows, и родной pthreads везде.

вы можете использовать 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;

Lock myLock;


void ReadFunction()
{
    ReadLock r_lock(myLock);
    //Do reader stuff
}

void WriteFunction()
{
     WriteLock w_lock(myLock);
     //Do writer stuff
}

Что бы вы ни решили использовать, проверьте свою рабочую нагрузку на простые блокировки, поскольку блокировки чтения/записи, как правило, в 3-40 раз медленнее, чем простой мьютекс, когда нет никаких разногласий.

здесь ссылка

изменить: ссылка на журнал MSDN больше не доступна. Статья CodeProject теперь доступна наhttps://www.codeproject.com/Articles/32685/Testing-reader-writer-locks и подводит итог довольно красиво. Также я нашел новую ссылку MSDN о Составные Объекты Синхронизации.

есть статьи о блокировках reader-writer на MSDN, который представляет некоторые их реализации. Он также вводит тонкий замок читателя / писателя, стержень примитив синхронизации введен с Vista. Там также есть статья CodeProject о сравнении различных реализаций (включая статьи MSDN).

Intel Thread Building Blocks также предоставляет несколько вариантов rw_lock:

http://www.threadingbuildingblocks.org/

Они имеют spin_rw_mutex для очень коротких периодов конкуренции и queueing_rw_mutex для более длительных периодов конкуренции. Первый может быть использован в особенно чувствительном к производительности коде. Последнее более сопоставимый по производительности с ускорение.Поток или непосредственно с помощью pthreads. Но профиль, чтобы убедиться, что один из них-это победа для ваших шаблонов доступа.

импульс.Нить С момента выпуска 1.35.0 уже поддерживает блокировки чтения-записи. Хорошая вещь в этом заключается в том, что реализация значительно кросс-платформенная, рецензируемая и на самом деле эталонная реализация для предстоящего стандарта C++0x.

и библиотека ACE, который обеспечивает множество запирая механизмов и перенесен к различным платформам.

в зависимости от граничных условий вашей задачи, вы можете найти следующие классы полезными:

  • ACE_RW_Process_Mutex
  • ACE_Write_Guard и ACE_Read_Guard
  • ACE_Condition

http://www.codeproject.com/KB/threads/ReaderWriterLock.aspx

вот хорошая и легкая реализация, подходящая для большинства задач.

класс блокировки синхронизации с несколькими читателями и одним писателем для Win32 от Glenn Slayde

http://www.glennslayden.com/code/win32/reader-writer-lock

в C++17 поддерживает std::shared_mutex . Он поддерживается в MSVC++ 2015 и 2017 годов.

вы можете скопировать солнце отлично ReentrantReadWriteLock. Он включает в себя такие функции, как дополнительная справедливость, блокировка понижения и, конечно же, повторная регистрация.

Да, это на Java, но вы можете легко прочитать и перенести его на C++, даже если вы не знаете никакой Java. Документация, с которой я связан, содержит все поведенческие свойства этой реализации, поэтому вы можете убедиться, что она делает то, что вы хотите.

Если ничего другого, это руководство.

Comments

    Ничего не найдено.