Последние GCC, например. GCC 5 поддерживает C11 и его thread_local
(при компиляции, например, с gcc -std=c11
). Как прокомментировал FUZxxl, вы можете использовать (вместо C11 thread_local
) квалификатор __thread
, поддерживаемый более старыми версиями GCC. Прочтите о локальном хранилище потоков.
pthread_getspecific
действительно довольно медленный (он находится в библиотеке POSIX, поэтому не предоставляется GCC, а, например, GNU glibc или musl-libc), поскольку он включает вызов функции. Использование переменных thread_local
, скорее всего, будет быстрее.
Просмотрите исходный код файла thread/pthread_getspecific.c
MUSL. для примера реализации. Прочтите этот ответ на соответствующий вопрос.
А _thread
и thread_local
(часто) не волшебным образом переводятся в вызовы pthread_getspecific
. Обычно они включают определенный режим адресации и/или регистр (подробности зависят от реализации и связаны с ABI). ; в Linux, я думаю, поскольку x86-64 имеет больше регистров и адресных режимов, его реализация TLS быстрее, чем на i386), с помощью компилятор, компоновщик и система выполнения. Напротив, может случиться так, что некоторые реализации pthread_getspecific
используют некоторые внутренние переменные thread_local
(в вашей реализации потоков POSIX).
Например, компиляция следующего кода
#include <pthread.h>
const extern pthread_key_t key;
__thread int data;
int
get_data (void) {
return data;
}
int
get_by_key (void) {
return *(int*) (pthread_getspecific (key));
}
использование GCC 5.2 (в Debian/Sid) с gcc -m32 -S -O2 -fverbose-asm
дает следующий код для get_data
с использованием TLS:
.type get_data, @function
get_data:
.LFB3:
.cfi_startproc
movl %gs:data@ntpoff, %eax # data,
ret
.cfi_endproc
и следующий код get_by_key
с явным вызовом pthread_getspecific
:
get_by_key:
.LFB4:
.cfi_startproc
subl $24, %esp #,
.cfi_def_cfa_offset 28
pushl key # key
.cfi_def_cfa_offset 32
call pthread_getspecific #
movl (%eax), %eax # MEM[(int *)_4], MEM[(int *)_4]
addl $28, %esp #,
.cfi_def_cfa_offset 4
ret
.cfi_endproc
Следовательно, использование TLS с __thread
(или thread_local
в C11), вероятно, должно быть быстрее, чем использование pthread_getspecific
(избегая накладных расходов на вызов).
Обратите внимание, что thread_local
— это удобный макрос, определенный в <threads.h>
(стандартный заголовок C11).
person
Basile Starynkevitch
schedule
27.08.2015
__thread
реализуется по-разному на разных платформах, на некоторых (вы не сказали, для какой из них вы программируете) это может быть реализовано с помощьюpthread_getspecific
. - person fuz   schedule 27.08.2015