如何安全地使用线程局部存储?

编程语言 2026-07-11

线程局部存储很棒。它允许我在一个线程中声明一个在堆上分配的对象,并在该线程终止时自动清除它。

然而,考虑这段代码:

static thread_local struct {
    char *data;
    uint32_t capacity;
} buffer = {.data = nullptr, .capacity = 0};
static thread_local tss_t buffer_tss;
if (!buffer.data) {
    tss_create(&buffer_tss, free);
    tss_set(buffer_tss, buffer.data = malloc(10 * sizeof(char)));
    buffer.capacity = 10;
}

把焦点放在 tss_set 调用上,也许在中间表示(IR)里是这样的:

_1 = malloc(10);
buffer.data = _1;
_2 = buffer.data;
buffer_tss.3 = buffer_tss;
tss_set(buffer_tss.3, _2);

那么,如果线程恰好在第1 行和第5 行之间终止,会调用 malloc,随后线程终止,因此我们没法把 buffer_tss 的内存写成结果。

或者这一行:

tss_set(buffer_tss, buffer.data = realloc(buffer.data, buffer.capacity * sizeof(char)));

以及它的中间表示(IR):

_1 = buffer.capacity;
_2 = (size_t)_1;
_3 = buffer.data;
_4 = realloc(_3, _2);
buffer.data = _4;
_5 = buffer.data;
buffer_tss.6 = buffer_tss;
tss_set(buffer_tss.6, _5);

如果线程在第4 行和第8 行之间终止,会怎样?数据被 realloced,因此 buffer_tss 的内存可能指向空值。然后,在我们还没来得及更新它时,线程就终止了,因此指向空值的指针将被 freed。

我是不是多虑了?如果不是,我该如何避免这种情况?

解决方案

线程只有在它愿意的时候才会终止。若谈及C11线程,根本没有办法让除了当前线程之外的线程终止。也没有C 标准库函数能实现这一点。如果谈及pthreads,你可以向某个线程发送取消请求,但该线程可能会退出并调用它的取消处理程序。再者,默认情况下,取消只会在定义明确的取消点发生,而你的代码片段并不具备这样的点。在Windows上,有 TerminateThread,但文档警告你这个函数很危险,除非你确切知道其他线程在做什么并且能保证它是安全的,否则不要调用它。

所以简短的结论是,线程在那些位置根本不会终止。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章