2010-12-14 4 views
1

sous Windows/C++, si j'ai un struct:Le partage d'une struct en toute sécurité entre plusieurs threads

struct ListItem { 
    ListItem* next; 
    ListItem* prev; 
    ... 
} 

avec plusieurs threads en cours d'exécution tant dans le processus principal et dans plusieurs DLL chargées dynamiquement, et tous ces fils besoin de partager la structure ci-dessus, comment puis-je les empêcher de piétiner les uns les autres? Quelque chose comme:

ListItem* list = ... 

A 

list->next = ... 

B 

Qu'est-ce que je mets en A et B pour éviter plus d'un fil à la fois en cours d'exécution list->next = ...?

+1

La première chose à faire est d'encapsuler la liste entière et tout ce qui l'accède directement dans une classe et forcer tout ce qui en veut l'accès à utiliser la classe. Cela empêchera le code dupliqué et garantira que tout ce qui utilise la liste respecte la méthode de synchronisation que vous aurez choisie. – Blrfl

Répondre

5

Il y a deux façons principales. L'un, peut-être le plus simple, consiste simplement à envoyer à chaque thread sa propre copie de la structure de données. De cette façon, vous n'aurez pas à utiliser la synchronisation pour protéger les données, car aucun thread ne partage les données d'un autre thread.

Mais cela ne fonctionnera pas dans beaucoup de situations. Parfois, vous avez vraiment besoin de partager une structure de données commune. Dans ce cas, vous devez protéger la structure de données avec une certaine forme d'objet de synchronisation. Boost.Threads fournit des plateformes multiplateformes, et je suis sûr que quelqu'un vous montrera comment les utiliser. Puisque vous avez demandé spécifiquement à propos de Windows, je vais vous montrer une méthode Windows.

Vous pouvez utiliser un CRITICAL_SECTION. Tout d'abord, vous devez initialiser la section critique dans votre fil conducteur, avant le coup d'envoi de vos threads de travail:

int main() 
{ 
// ... 
    CRITICAL_SECTION cs; 
    InitializeCriticalSection(&cs); 
// ... 
} 

passe ensuite le pointeur sur le cs à chaque thread de travail. (Ceci est laissé comme un exercice.) Dans chaque thread de travail, entrez le cs avant de travailler avec vos données, et laissez-le lorsque vous avez terminé.

CRITICAL_SECTION* pcs = ...; // passed in from main thread 
EnterCriticalSection(pcs); // this will block until the cs is "available" 
list->next = ... 
LeaveCriticalSection(pcs); // makes the cs available to other threads 

Ce qui précède est psudocode, et a beaucoup de place pour l'amélioration. Par exemple, la section critique doit être enveloppée dans un objet RAII afin qu'il soit automatiquement détruit lorsque vous avez terminé. De même, le verrouillage et le déverrouillage doivent également être effectués dans un objet RAII afin qu'il soit toujours déverrouillé, peu importe comment vous quittez votre fonction de thread, même face à des exceptions.

Notez qu'une CRITICAL_SECTION ne peut être utilisée que par un seul processus. Si vous devez utiliser un objet de type mutex sur plusieurs processus (pas ce dont vous avez besoin ici), alors vous devez utiliser un named mutex à la place.

+0

Merci! Désolé je ne connaissais pas les mots corrects pour cela, mais après avoir regardé votre lien CRITICAL_SECTION je vois que c'est ce dont j'ai besoin. :) – storm

+0

@storm: Profitez et bonne chance –

0

Utilisez des objets Windows Mutex dans lesquels vous avez plusieurs processus pouvant accéder à une ressource. Si vos threads sont tous sur un processus, vous pouvez utiliser EnterCriticalSection/LeaveCriticalSection.

+0

Comment cette structure peut-elle être partagée entre processus? CriticalSection est ce qui est nécessaire, ou mieux une classe lock_guard qui l'encapsule. –

+0

Je n'ai pas réellement fait cela, mais dans Windows on peut créer de la mémoire partagée interprocessus. Jetez un pointeur dans cette mémoire pour empiler *. Protégez l'accès avec un mutex nommé. Voilà. – ThomasMcLeod

+0

Fichiers partagés Windows et mémoire: http://msdn.microsoft.com/en-us/library/aa366878(VS.85).aspx – ThomasMcLeod

0

Est-ce ce devoir? Dans tous les cas, essayez de googler "Critical Section".

+0

Je doute que ce soit des devoirs. –

0

En fonction de ce dont vous avez besoin pour la structure, vous pouvez utiliser une structure de données sans verrou, telle que Win API interlocked SList. De cette façon, même lorsque plusieurs threads effectuent des opérations, la structure de données est toujours cohérente.

Questions connexes