73 votes

Lecteur / Ecrivain se verrouille en C ++

Je cherche un bon lecteur / rédacteur en C ++. Nous avons un cas d'utilisation d'un seul écrivain peu fréquent et de nombreux lecteurs assidus et nous souhaitons optimiser cela. De préférence, je souhaiterais une solution multiplate-forme, mais une solution Windows uniquement serait acceptable.

49voto

Yochai Timmer Points 19802

Vous pouvez utiliser boost pour créer un verrou en lecture-écriture:

 #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
}
 

37voto

Greg Rogers Points 18119

Des versions plus récentes de boost::thread de lecture/écriture de serrures (1.35.0 et, plus tard, apparemment les versions antérieures ne fonctionnent pas correctement).

Ils ont les noms shared_lock, unique_lock, et upgrade_lock et opèrent sur un shared_mutex.

36voto

ephemient Points 87003

En utilisant le standard de pré-testé, pré-construit des choses est toujours bonne (par exemple, poussée comme une autre réponse proposé), mais c'est quelque chose qui n'est pas trop dur à construire vous-même. Voici un peu stupide de la mise en œuvre tirée à partir d'un projet de la mine:

#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 n'ont pas vraiment le Windows natif, mais l'idée générale est là. Cette mise en œuvre est légèrement biaisé en faveur des écrivains (une horde d'écrivains peuvent mourir de faim lecteurs indéfiniment); il suffit de modifier writer_unlock si vous préférez la balance dans l'autre sens.

Oui, c'est du C et pas du C++. La traduction est un exercice laissé au lecteur.

Modifier

Greg Rogers a fait valoir que la norme POSIX ne précise pas de pthread_rwlock_*. Ce n'est pas vous aider si vous n'avez pas pthreads, mais il a remué mon esprit à se souvenir: Pthreads-w32 devrait fonctionner! Au lieu de porter ce code à la non-pthreads pour votre propre usage, il suffit d'utiliser les Pthreads-w32 sur Windows, et natif pthreads partout ailleurs.

16voto

ididak Points 4208

Quoi que vous décidiez d'utiliser, comparez votre charge de travail à de simples verrous, car les verrous en lecture / écriture ont tendance à être 3 à 40 fois plus lents que les simples mutex, lorsqu'il n'y a pas de conflit.

Voici une référence

10voto

vividos Points 1933

Il existe un article sur les verrous lecteur-écrivain sur MSDN qui en présente certaines implémentations. Il introduit également le verrou lecteur / graveur Slim, une primitive de synchronisation du noyau introduite avec Vista. Il existe également un article CodeProject sur la comparaison de différentes implémentations (y compris celles de l'article MSDN).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X