пример специфичных для потока данных в C - PullRequest
2 голосов
/ 15 ноября 2009

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

Я пользователь Linux!

Ответы [ 5 ]

7 голосов
/ 15 ноября 2009

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

С помощью gcc вы можете объявить переменную как специфичную для потока, используя атрибут "__thread". Если вы только пытаетесь создать примитивный тип, специфичный для потока, и имеете дело только с Linux и GCC, то это возможное решение. Если вы действительно хотите быть переносимым между различными единицами (желаемая цель), или если вы хотите сделать сложные типы данных ориентированными на потоки, то для этого вам нужно использовать подпрограммы UNIX ...

В UNIX он работает так, что вы используете phread_key_create перед тем, как создавать потоки, чтобы создать уникальное имя переменной. Затем вы используете phread_setspecific и pthread_getspecific для изменения / доступа к данным, связанным с ключом. Семантика определенных функций set / get заключается в том, что ключ ведет себя как индекс в карте, где каждый поток имеет свою собственную карту, поэтому выполнение этих подпрограмм из разных потоков приводит к доступу / изменению разных данных. Если вы можете использовать карту, вы можете использовать хранилище для конкретных потоков.

Очевидно, что когда вы закончите, вам нужно вызвать соответствующие подпрограммы для очистки данных. Вы можете использовать pthread_cleanup_push , чтобы запланировать процедуру очистки для освобождения любых структур данных, связанных с ключом потока, и вы можете использовать pthread_key_destroy , когда ключ больше не используется.

5 голосов
/ 15 ноября 2009

Хорошим примером является переменная errno из исходной библиотеки времени выполнения C. Если у процесса есть два потока, выполняющих системные вызовы, было бы очень плохо, если бы это была общая переменная.

нить 1:

int f = open (...);
if (f < 0)
    printf ("error %d encountered\n", errno);

нить 2:

int s = socket (...);
if (s < 0)
    printf ("error %d encountered\n", errno);

Представьте себе путаницу, если open и socket вызывается примерно в одно и то же время, оба как-то терпят неудачу, и оба пытаются показать номер ошибки!

Чтобы решить эту проблему, многопоточные библиотеки времени выполнения делают errno элементом данных, специфичных для потока.

4 голосов
/ 15 ноября 2009

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

Когда переменная должна быть разной для каждого потока, если вы используете реализацию, совместимую с ISO-C99 (например, GCC), вам нужно только добавить ключевое слово класса хранения __thread в объявление переменной, как в:

__thread char *variable;

Это даст указание всем уровням в цепочке сборки (cc, ld, ld.so, libc.so и libpthread.so) манипулировать этой переменной специальным, специфичным для потока способом.

Следующие компиляторы поддерживают этот синтаксис (cf wikipedia ):

  • Sun Studio C / C ++
  • IBM XL C / C ++
  • GNU C
  • Intel C / C ++ (системы Linux)
  • Borland C ++ Builder
0 голосов
/ 15 ноября 2009

Это хороший пример, если вы работаете на платформе Windows

http://msdn.microsoft.com/en-us/library/ms686991(VS.85).aspx

0 голосов
/ 15 ноября 2009
...