【发布时间】:2019-02-08 16:40:36
【问题描述】:
我正在阅读 Kerrisk's book 并看到以下内容作为 31-4 的注释,
__thread关键字必须紧跟static或extern关键字,如果在变量的 声明。- 线程局部变量的声明可以包括初始化程序,其方式与普通全局变量或静态变量相同 声明。
- C 地址 (&) 运算符可用于获取线程局部变量的地址。
我想知道关键字必须在static或extern后面的原因。没有它们就不能使用吗?
它的示例代码,
/*************************************************************************\
* Copyright (C) Michael Kerrisk, 2018. *
* *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation, either version 3 or (at your option) any *
* later version. This program is distributed without any warranty. See *
* the file COPYING.gpl-v3 for details. *
\*************************************************************************/
/* strerror_tls.c
An implementation of strerror() that is made thread-safe through
the use of thread-local storage.
See also strerror_tsd.c.
Thread-local storage requires: Linux 2.6 or later, NPTL, and
gcc 3.3 or later.
*/
#define _GNU_SOURCE /* Get '_sys_nerr' and '_sys_errlist'
declarations from <stdio.h> */
#include <stdio.h>
#include <string.h> /* Get declaration of strerror() */
#include <pthread.h>
#include "tlpi_hdr.h"
#define MAX_ERROR_LEN 256 /* Maximum length of string in per-thread
buffer returned by strerror() */
/* ||||||||||||||||||
// vvvvvvvvvvvvvvvvvv
*/
static __thread char buf[MAX_ERROR_LEN];
/* Thread-local return buffer */
char *
strerror(int err)
{
if (err < 0 || err >= sys_nerr || sys_errlist[err] == NULL) {
snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);
} else {
strncpy(buf, sys_errlist[err], MAX_ERROR_LEN - 1);
buf[MAX_ERROR_LEN - 1] = '\0'; /* Ensure null termination */
}
return buf;
}
static void *
threadFunc(void *arg)
{
char *str;
printf("Other thread about to call strerror()\n");
str = strerror(EPERM);
printf("Other thread: str (%p) = %s\n", str, str);
return NULL;
}
int
main(int argc, char *argv[])
{
pthread_t t;
int s;
char *str;
str = strerror(EINVAL);
printf("Main thread has called strerror()\n");
s = pthread_create(&t, NULL, threadFunc, NULL);
if (s != 0)
errExitEN(s, "pthread_create");
s = pthread_join(t, NULL);
if (s != 0)
errExitEN(s, "pthread_join");
/* If strerror() is not thread-safe, then the output of this printf() be
the same as that produced by the analogous printf() in threadFunc() */
printf("Main thread: str (%p) = %s\n", str, str);
exit(EXIT_SUCCESS);
}
【问题讨论】:
-
__thread甚至是关键字吗?我在搜索 C 标准时没有看到它。这是_Thread_local的自定义别名吗? -
示例代码有很多问题,比如使用
_sys_errlist,它已被弃用、不安全,并且引入了对特定版本 glibc程序链接的ABI依赖反对,由于复制重定位混乱。 -
贴出的代码无法编译!这可以通过头文件的内容来修复:
lpi_hdr.h但是,您的问题中缺少该文件的内容。 -
_Thread_local是线程局部变量的 C11 / C18 标准表示法。__thread符号牢牢地位于“为系统保留”的名称空间中;它可以做任何事情,但功能可能有点像_Thread_local,定义该变量是线程局部变量。它与__declspec(thread)没有太大区别——既不好也不坏。
标签: c multithreading thread-safety thread-local-storage