3 votes

c++ pthread - Comment rendre l'accès aux cartes sûr pour les fils ?

J'ai une carte comme variable membre et plusieurs threads qui accèdent à la carte (accès en lecture et en écriture). Maintenant, je dois m'assurer qu'un seul thread a accès à la carte. Mais comment puis-je le faire ? Quelle est la meilleure solution pour cela ?

4voto

Tudor Points 39539

Boost contient de belles implémentations de verrous pour l'accès partagé. Jetez un coup d'œil à la documentation .

Dans votre cas, vous avez probablement besoin d'un verrou de lecture-écriture, car un verrou d'exclusion mutuelle est probablement excessif si vous avez beaucoup de lectures et très peu d'écritures.

3voto

dasblinkenlight Points 264350

Vous avez besoin de synchroniser l'accès à votre carte, par exemple en utilisant une Mutex POSIX . Le lien contient quelques exemples simples à suivre sur la façon d'utiliser les variables d'exclusion mutuelle.

1voto

Matthieu M. Points 101624

En fait, le principe selon lequel un seul fil d'exécution doit accéder à l'espace de travail de l'ordinateur de l'entreprise n'est pas pertinent. map à un moment donné est légèrement décalé.

Les lectures simultanées sont acceptables, ce que vous voulez éviter, c'est qu'un thread modifie la carte pendant que les autres la lisent.

Selon le niveau de granularité dont vous avez besoin, vous pouvez envisager un verrou lecteur/écrivain, qui permettra à plusieurs lectures de se dérouler en parallèle.

L'usage exact a été démontré ici en utilisant Boost :

boost::shared_mutex _access;
void reader()
{
  // get shared access
  boost::shared_lock<boost::shared_mutex> lock(_access);

  // now we have shared access
}

void writer()
{
  // get upgradable access
  boost::upgrade_lock<boost::shared_mutex> lock(_access);

  // get exclusive access
  boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
  // now we have exclusive access
}

Après cela, il s'agit simplement d'envelopper de manière pratique l'accès à la carte. Par exemple, vous pouvez utiliser une structure proxy générique :

template <typename Item, typename Mutex>
class ReaderProxy {
public:
  ReaderProxy(Item& i, Mutex& m): lock(m), item(i) {}

  Item* operator->() { return &item; }

private:
  boost::shared_lock<Mutex> lock;
  Item& item;
};

template <typename Item, typename Mutex>
class WriterProxy {
public:
  WriterProxy(Item& i, Mutex& m): uplock(m), lock(uplock), item(i) {}

  Item* operator->() { return &item; }

private:
  boost::upgrade_lock<Mutex> uplock;
  boost::upgrade_to_unique_lock<Mutex> lock;
  Item& item;
};

Et vous pouvez les utiliser comme :

class Foo {
  typedef ReaderProxy< std::map<int, int>, boost::shared_mutex> Reader;
  typedef WriterProxy< std::map<int, int>, boost::shared_mutex> Writer;

public:
  int get(int k) const {
    Reader r(map, m);

    auto it = r->find(k);
    if (it == r->end()) { return -1; }
    return it->second;
  }

  void set(int k, int v) {
    Writer w(map, m);

    w->insert(std::make_pair(k, v));
  }
private:
  boost::shared_mutex m;
  std::map<int, int> map;
};

Attention toutefois aux itérateurs, ils ne peuvent être manipulés en toute sécurité que lorsque le mutex est détenu par le thread actuel.

De plus, je vous recommande de contrôler étroitement la carte, en la faisant entrer dans les plus petits objets qui ont un sens, et de ne fournir que les opérations dont vous avez besoin. Moins les méthodes ont accès à la carte, moins vous risquez de manquer un point d'accès.

1voto

hirschhornsalz Points 16306

Si vous avez un compilateur récent, vous pouvez utiliser std::mutex (qui est basé sur l'implémentation de Boost). Cela fait partie de C++11, donc il n'est pas implémenté partout. gcc-4.6 fonctionne assez bien cependant. L'implémentation sous-jacente est constituée de threads POSIX sous linux et de threads Windows sous Windows.

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