- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在阅读 Kerrisk's book并看到以下作为 31-4 的注释,
- The
__thread
keyword must immediately follow thestatic
orextern
keyword, if either of these is specified in the variable’s declaration.- The declaration of a thread-local variable can include an initializer, in the same manner as a normal global or static variable declaration.
- The C address (&) operator can be used to obtain the address of a thread-local variable.
我想知道关键字必须在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);
}
最佳答案
线程局部变量的标准 C 存储类说明符是 _Thread_local
.该标准还在 §6.11 Future directions 中说:
6.11.5 Storage class specifiers
The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.
因此,标准规定存储类关键字(static
、extern
、auto
— 不要使用它! — register
— 同上 — _Thread_local
和 typedef
) 应该出现在声明的开头。出现static
或extern
和_Thread_local
的地方,书上推荐的是static
或extern
应该是第一个,_Thread_local
第二个。
当然,本书使用的是__thread
,而不是_Thread_local
。这是一个特定于编译器(实现)的关键字,其行为类似于标准 C _Thread_local
和 Microsoft 的 __declspec(thread)
。
关于 thread local storage 的 GCC 文档文档(强调已添加):
At the user level, the extension is visible with a new storage class keyword:
__thread
. For example:__thread int i;
extern __thread struct state s;
static __thread char *p;The
__thread
specifier may be used alone, with theextern
orstatic
specifiers, but with no other storage class specifier. When used withextern
orstatic
,__thread
must appear immediately after the other storage class specifier.The
__thread
specifier may be applied to any global, file-scoped static, function-scoped static, or static data member of a class. It may not be applied to block-scoped automatic or non-static data member.
因此,您看到的是 GCC 特定于线程本地存储的表示法,正如我所指出的和 GCC 手册所指出的那样,存储类信息应该在声明中排在第一位(并且 GCC 明确指出 __thread
在 static
或 extern
之后。
关于c - 为什么 __thread 必须跟在 extern 或 static 之后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54596755/
我有这样一个使用静态变量的函数。现在我需要在多线程应用程序中使用它。 char * ether_ntoa(const struct ether_addr *n) { static char a
我找不到任何可以告诉我 __thread 关键字/特征是否存在的函数/宏。 例如,我想在没有用户定义 HAS_TLS 的情况下做这样的事情 #if HAS_TLS static __threa
我真的很困惑 gcc __thread 的关键字在背后做了什么。 谁能给我一些信息? 最佳答案 它将变量声明为 thread local与 C++11 thread_local 关键字的方式非常相似,
嗨,我正在使用 C 库对机器人进行编程。阅读时代码中,我遇到了术语“_thread”,我不知道是什么是不是意味着.我试图搜索该项目,看看是否“_thread”上有任何定义,但没有意义大部头书。我猜下面
我想在 g++ 中使用 __thread 修饰符来替代 C++11 中的 thread_local。不幸的是,我的本地线程变量没有简单的构造函数(它必须设置一个整数分量的值)。我考虑使用这种构造: _
如果我在全局范围内定义一个静态 __thread 变量,它是否等同于常规的非静态全局变量?也就是说,如果以下两个变量都在全局范围内,它们是否等价: int regular_global_int; st
gcc中的__thread是如何实现的?它只是 pthread_getspecific 和 pthread_setspecific 的包装器吗? 我的程序使用 TLS 的 posix API,现在我有
我正在实现一个极其轻量级的 pthread 替换库。我想完全禁用 __thread 有几个原因。 这是浪费内存。如果我正在创建一千个与使用 __thread 声明变量的上下文无关的线程,它们仍将分配
考虑以下代码: #include __thread bool foo = true; int main() { printf("foo = %d\n", foo); return 0
我正在尝试使用 __thread 说明符来创建一个线程局部变量。这在以下代码中工作正常: #include #include static __thread int val; int main()
我想使用 __thread 存储类将一些变量定义为线程特定的。但是三个问题让我犹豫不决: 它真的是c99的标准吗?或者更重要的是,编译器支持有多好? 是否会在每个线程中初始化变量? 非多线程程序是否将
我所有的static __thread值显示为 当在调试时我想观察变量的值时;即使使用 -o0 和/或 volatile . Static没有 __thread 的变量正确显示。 即使我正在使用线程,
这是我的示例程序, int main() { static __thread int a; printf("\n %d",a); return 0; } 在这个程序中,当 print
我正在维护一个库,该库具有需要线程特定变量的函数。由于 gcc 4.2 中的错误,如果我定义x 中的静态 __thread;当从 PERL 通过未命名的 API 调用库函数时,它挂起。 我想使用 pt
我读到 C++ 中有一个新关键字:它是我读过的 __thread。 我只知道它是一个可以像 static 关键字一样使用的关键字,但我什么都不知道。这个关键字是否仅仅意味着,例如,如果一个变量是这样声
我正在尝试编写一些库代码,可供启用(或未启用)pthreads 的人员以及启用(或不启用)openmp 支持的人员使用。我有一些变量我真的想放在线程本地存储中。例如,指定两次是否有任何潜在的危害 #i
运行夹板 matt@stanley:~/cpfs$ splint -paramuse +gnuextensions cpfs.c 在此行暂停: __thread int cpfs_errno; 出现解
我目前有一个包含一些全局变量的库。我想让这些变量成为本地线程,所以我在它们前面添加了“__thread”说明符。它完成了工作,但编译器对这些变量给出了“定义但未使用”的警告。我用“-Wno-unuse
我正在阅读 Kerrisk's book并看到以下作为 31-4 的注释, The __thread keyword must immediately follow the static or ext
C++11 标准包含一个新的附加项——thread_local 说明符——它使静态变量成为线程局部的。标准的 thread_local 支持非平凡的类型——那些具有构造函数和析构函数的类型。遗憾的是,
我是一名优秀的程序员,十分优秀!