Обеспечение безопасности многопоточности глобальных статических переменных

StackOverflow https://stackoverflow.com/questions/2662575

Вопрос

У меня есть глобальные статические переменные в библиотеке C, которые генерируют исключения при многопоточном запуске.Мне нужно каким-то образом сделать их безопасными (т. е. каждый поток должен относиться к другому экземпляру этих переменных).Какие-нибудь рекомендуемые методы?

Это было полезно?

Решение

Нет стандартного способа, который работает во всех реализациях C, но существуют решения, специфичные для реализации. Например, с компилятором Microsoft (см. Документы),

__declspec( thread ) int tls_i = 1;

произносить tls_i Live в потоке - локальное хранилище (каждый поток имеет свой отдельный экземпляр этой переменной). С участием GCC., синтаксис

__thread int tls_i;

Вы также можете проверить Вход в Википедии по теме.

Другие советы

Первый вопрос:

  • нужны ли потокам собственные копии переменных?
  • или им нужно координировать доступ к одной общей копии?

Если вам нужно первое, в других ответах были сделаны предложения о "локальном хранилище потоков".

Если вам нужно последнее, то так или иначе вам нужно убедиться, что для этих переменных есть соответствующий мьютекс (область действия мьютекса является одной из проблем, с которыми вы сталкиваетесь), и что все потоки используют мьютекс и освобождают мьютекс.Это гораздо сложнее.Возможно даже, что вам нужно предоставить функции, управляющие доступом к переменным.

Стандартная переменная errno может быть изменяемым значением lvalue:

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

В потоковом приложении (скомпилированном с помощью -DREENTRANT) происходит вот что;в macOS X, похоже, это то, что происходит в любом случае (они используют название __error вместо того, чтобы _errno_func;оба находятся в пространстве имен реализации).

Возможно, вы захотите или в конечном итоге вам придется сделать что-то подобное для ваших переменных.Тот факт, что вы говорите, что они статичны, немного улучшает ситуацию.У вас есть только один файл для работы (если только вы не настолько неосторожны, чтобы передавать указатели назад или на эти переменные).

Что вам нужно, это TLS (поток локального хранения), который также известен как данные с нитью данные или Нить-частные данные. Отказ Этот механизм может гарантировать каждому потоку для доступа к своей отдельной копии данных, не беспокоясь о синхронизации доступа с другими потоками.


Существует два метода для использования TLS:

  1. неявный: с использованием ключевого слова

    Windows: __declspec (поток) int tls_var = 10;

    Linux с GCC: __thread int tls_var = 10

  2. явное: с использованием конкретных TLS, связанных с API

    Windows:

      Tlsalloc (): выделить память для данных TLS
      Tlsfree (): Бесплатно память данных TLS
      TlsSetValue (): Установите значение TLS
      TlsgetValue (): получить значение TLS

    Пожалуйста, обратитесь к MSDN для получения подробной информации.

    Linux с GCC:

      pthread_key_create (): Создайте данные TLS
      pthread_key_delete (): Destory Data TLS
      pthread_getspecific (): получить значение TLS
      pthread_setspecific(): установить значение TLS
    Обратитесь к Ampage для конкретной и подробной информации.

Большинство компиляторов имеют какой-то способ назначения ниток-локального хранения. Предполагая, что это доступно, вот что вы хотите.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top