为什么在pthread中需要线程特定数据?

时间:2011-03-04 06:55:27

标签: c linux pthreads

所有线程共享内存位置。例如,一个线程中的全局变量更改将反映在另一个线程中。由于每个线程都有自己的堆栈,因此本地 在线程内创建的变量是唯一的。在这种情况下,我们为什么需要 去寻找特定于线程的数据机制?无法通过自动存储变量来实现 在线程函数内部?

请澄清!!!。

BR RJ

5 个答案:

答案 0 :(得分:3)

正常的全局变量在线程之间共享。局部变量特定于函数的特定调用。如果你想要在同一个线程中运行但对该线程唯一的一些函数可以看到(例如)某些东西,那么特定于线程的数据就是你要找的东西。

答案 1 :(得分:1)

这不是必需的,但它相当方便。某些函数(如randstrtok)使用静态存储持续时间信息,这在线程之间共享时可能会出现问题。

假设您有一个随机数函数,您希望为每个线程维护不同的序列(因此为种子)。你有两种方法。

你可以使用像kludgy这样的东西:

int seed;
srand (&seed, time (NULL));
int r = rand_r (void *seed);

其中种子必须由调用者创建并在每次传递。

或者你可以使用相当好的,符合ISO标准的:

srand (time (NULL));
int r = rand();

使用线程本地存储来维护特定于线程的种子。与strtok关于其正在处理的字符串中的位置使用的信息类似。

这样,您就不必在线程和非线程版本之间更改代码了。

现在你可以在线程函数中创建该信息,但是rand函数如何在不传递它的情况下知道它的地址。如果rand被称为87堆栈级别会怎么样?转移指针的过程非常多。

而且,即使你做了类似的事情:

void pthread_fn (void *unused) {
    int seed;
    rand_set_seed_location (&seed);
    :
}

rand随后使用该值,无论它在堆栈中有多深,这仍然是标准的代码更改。它可能有用,但也可以在COBOL中编写操作系统。这不是一个好主意: - )

答案 2 :(得分:0)

是的,堆栈是分配线程本地存储的一种方式(包括特定线程本地堆分配的句柄)。

答案 3 :(得分:0)

线程特定数据的最佳示例是“ errno ”。当对c库中某些功能的调用失败时, errno 已设置,您可以检查它以找出失败的原因。如果没有特定于线程的数据,则无法将这些函数移植到多线程环境,因为在检查之前,其他线程可以设置 errno

答案 4 :(得分:0)

作为一般规则,新API中应避免使用TSD。如果函数需要某些信息,则应将其传递给它。

但是,有时您需要TSD来“克制”API缺陷。一个很好的例子是'gmtime'。 'gmtime'函数返回一个指向结构的指针,该结构在下次调用'gmtime'之前有效。但这会使'gmtime'在多线程程序中难以使用。如果某个图书馆在你没想到的时候称之为“gmtime”,会破坏你的结构怎么办?一个简单的解决方法是使结构返回特定于线程。 (当然,长期解决方案是创建一个更合适的API,例如'gmtime_r'。)

在新设计中使用TSD非常合理的一种情况是,不会频繁访问会混淆API的信息。例如,如果发现了一个严重错误,那么从更高级别的代码中记录某些上下文信息可能会很好(您在服务哪个客户端?他们发送了什么命令?)。您的选择基本上是将此上下文信息从函数传递到函数(如果某些函数不在您的控件之内,这甚至不可能),或者将它存储在TSD中。