2010-04-18 10 views
4

J'ai des variables statiques globales dans une bibliothèque C, qui génèrent des exceptions dans une exécution multithread. J'ai besoin de les sécuriser d'une manière ou d'une autre (c'est-à-dire que chaque thread doit se rapporter à une instance différente de ces variables). Toutes les méthodes recommandées?Rendre les variables statiques globales multithread safe

Répondre

9

Il n'existe pas de méthode standard qui fonctionne dans toutes les implémentations C, mais des solutions spécifiques à l'implémentation existent. Par exemple, avec le compilateur Microsoft (voir the docs),

__declspec(thread) int tls_i = 1; 

fait tls_i en direct dans le stockage local des threads (chaque thread a sa propre instance distincte de cette variable). Avec gcc, la syntaxe est

__thread int tls_i; 

Vous pouvez également consulter la wikipedia entry sur le sujet.

+0

Quelque chose de spécifique à gcc? – giladsah

+0

@giladsah: Lire la seconde moitié de la réponse! –

+0

@giladsah, bien sûr, le mot-clé '__thread' comme je viens de le dire dans ma réponse (j'ai aussi pointé vers une page doc' gcc' sur le stockage local-thread pour plus de détails). –

1

La plupart des compilateurs ont un moyen de désigner le stockage local. En supposant que c'est disponible, c'est ce que vous voulez.

4

Première question:

  • les fils doivent faire leurs propres copies des variables?
  • ou doivent-ils coordonner l'accès à une seule copie partagée?

Si vous avez besoin du premier, les autres réponses ont fait des suggestions sur le 'stockage local du thread'. Si vous avez besoin de ce dernier, alors vous devez vous assurer qu'il existe un mutex approprié sur ces variables (la portée du mutex est l'un des problèmes que vous rencontrez), et que les threads utilisent tous le mutex, et relâchez le mutex. C'est plus compliqué. Il se peut même que vous deviez fournir des fonctions contrôlant l'accès aux variables.

La variable errno standard peut être une lvalue modifiable:

extern int *_errno_func(void); 
#define errno (*(_errno_func)()) 

Dans une application filetée (compilé avec -DREENTRANT), c'est ce qui se passe; sur MacOS X, il semble que ce soit ce qui se passe de toute façon (ils utilisent le nom __error au lieu de _errno_func, les deux sont dans l'espace de noms de l'implémentation).

Vous voudrez peut-être faire quelque chose de similaire pour vos variables. Le fait que vous disiez qu'ils sont statiques améliore un peu les choses. Vous n'avez qu'un seul fichier à traiter (à moins que vous ne soyez assez imprudent pour passer en arrière - ou sur - des pointeurs vers ces variables).

3

Qu'est-ce que vous avez besoin est TLS (Thread Local Storage), qui est également connu sous le nom des données spécifiques au thread ou données thread-privé. Ce mécanisme peut garantir à chaque thread d'accéder à sa propre copie de données, sans se soucier de synchroniser l'accès avec d'autres threads.


Il existe deux méthodes pour utiliser TLS:

  1. implicite: en utilisant le mot

    Fenêtres: __declspec (thread) int tls_var = 10;

    Linux avec GCC: __thread int tls_var = 10

  2. explicite: en utilisant TLS spécifiques API liées

    Fenêtres:

      TlsAlloc(): allouer de la mémoire pour les données tls
      TlsFree(): libérer la mémoire des données tls
      TlsSetValue(): set tls de valeur
      TlsGetValue(): se tls de la valeur

    S'il vous plaît se référer à MSDN pour plus d'informations.

    LInux avec GCC:

      pthread_key_create(): créer les données de tls
      pthread_key_delete(): destory les données tls
      pthread_getspecific(): obtenir la valeur tls
      pthread_setspecific(): définissez la valeur de tls
    Accédez à la page de manuel pour obtenir des informations spécifiques et détaillées.

Questions connexes