Sécurité des threads pour la queue STL

J’utilise une queue pour communiquer entre les threads. J’ai un lecteur et plusieurs threads d’écrivain. Ma question est la suivante: dois-je verrouiller la queue chaque fois que j’utilise Push / Front / Pop de la queue pour le lecteur? Puis-je faire quelque chose comme ce qui suit:

//reader threads getLock(); get the number of elements from the queue releaseLock(); int i = 0; while( i < numOfElements){ queue.front(); queue.pop(); i++ } 

L’idée est que je souhaite réduire la granularité du code verrouillé et que le thread d’écriture n’écrirait qu’à l’arrière de la queue et qu’il n’y a qu’un seul thread de lecteur. Tant que je reçois le nombre d’éléments, je peux obtenir les éléments de la queue OU dois-je également enfermer front() et pop() dans le verrou?

Comme d’autres l’ont déjà mentionné, les conteneurs standard ne sont pas tenus de garantir la sécurité des filets. Par conséquent, ce que vous demandez ne peut pas être mis en œuvre de manière portable. Vous pouvez réduire le temps que votre thread de lecteur verrouille les rédacteurs en utilisant 2 files d’attente et un pointeur de queue qui indique la file actuellement utilisée par les rédacteurs.

Chaque écrivain:

  • Acquérir un verrou
  • Insérez des éléments dans la queue actuellement pointée par le pointeur de la queue
  • Déverrouiller

Le lecteur peut alors faire ce qui suit:

  • Acquérir un verrou
  • Basculer le pointeur de la queue pour qu’il pointe vers la deuxième queue
  • Déverrouiller
  • Traiter les éléments de la première file

Tout type qui n’énonce pas explicitement ses garanties de sécurité des threads doit toujours être contrôlé par un mutex. Cela dit, la stdlib de votre implémentation peut permettre certaines variations, mais vous ne pouvez pas savoir pour toutes les implémentations de std :: queue.

Comme std :: queue enveloppe un autre conteneur (c’est un adaptateur de conteneur), vous devez examiner le conteneur sous-jacent, qui par défaut est deque.

Vous constaterez peut-être qu’il est plus facile, plus efficace ou plus portable d’écrire votre propre adaptateur de conteneur offrant les garanties dont vous avez besoin. Je ne connais rien qui fasse exactement cela pour une queue dans Boost.

Je n’ai pas suffisamment regardé C ++ 0x pour savoir s’il a une solution à ce problème, mais cela pourrait être une autre option.

Ceci dépend absolument de la mise en œuvre. La norme C ++ fait mention des threads ou de la sécurité des threads. Par conséquent, son fonctionnement dépend de la manière dont votre implémentation gère les éléments de la queue.

Dans votre cas, le lecteur ouvre la queue, ce qui est considéré comme une opération d’écriture. Je doute que les implémentations courantes garantissent réellement la sécurité des threads dans ce cas, lorsque plusieurs threads écrivent simultanément dans un conteneur. Au moins VC ++ ne:

Pour les lectures sur le même object, l’object est thread-safe pour la lecture lorsqu’il n’y a pas d’écrivain sur d’autres threads.

Pour les écritures dans le même object, l’object est thread-safe pour écrire à partir d’un thread alors qu’aucun lecteur n’est présent sur d’autres threads.

Parfois, vous pouvez résoudre beaucoup de problèmes de concurrence en évitant de partager l’état ou les ressources entre les threads. Si vous avez plusieurs threads qui accèdent simultanément à un conteneur pour intégrer leur travail, essayez de les faire fonctionner sur des conteneurs dédiés. À des points spécifiques, vous collectez ensuite les éléments des conteneurs sur le conteneur central de manière non concurrente.

Si vous pouvez éviter de partager l’état ou les ressources entre les threads, vous n’aurez aucun problème à les exécuter simultanément. Les fils ne doivent alors pas s’inquiéter les uns des autres, car ils sont complètement isolés et n’ont aucun effet les uns sur les autres.

Votre intuition est correcte: même si vous ne pouvez pas compter sur la file d’attente STD pour la sécurité des threads, une file d’attente devrait l’être par la conception .

Van Dooren donne une bonne explication de cette situation et donne une implémentation standard des files d’attente sans verrouilage en threading C ++ sécurisées pour les threads.