【问题标题】:Why thread specific data is required in pthread?为什么在 pthread 中需要特定于线程的数据?
【发布时间】:2011-07-08 14:53:50
【问题描述】:

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

请澄清!!!。

BR Rj

【问题讨论】:

  • 所有全局变量默认在所有线程之间共享。 IIRC,线程特定数据可用于指定其他变量,其中变量具有相同的名称但特定于线程。

标签: c linux pthreads


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    普通全局变量在线程之间共享。局部变量特定于函数的特定调用。如果您想要(例如)对同一线程中运行的多个函数可见但对该线程唯一的东西,那么线程特定数据就是您要查找的内容。

    【讨论】:

      【解决方案3】:

      这不是必需的,但它相当方便。 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 中编写操作系统也可能有效。这并不是一个好主意:-)

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • glibc中的errno是由线程特定的数据实现的,我们随便用,不用担心争用。
        【解决方案5】:

        作为一般规则,应避免在新 API 中使用大多数 TSD。如果一个函数需要一些信息,它应该被传递给它。

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

        在新设计中完全合理地使用 TSD 的一种情况是用于不经常访问的信息,这会使 API 变得混乱。例如,如果发现了严重错误,最好从更高级别的代码中记录某些上下文信息(您服务的是哪个客户端?他们发送了什么命令?)。您的选择基本上是将上下文信息从一个函数传递到另一个函数(如果某些函数超出您的控制范围,这甚至不总是可能的)或将其存储在 TSD 中。

        【讨论】:

          猜你喜欢
          • 2021-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-15
          • 1970-01-01
          • 1970-01-01
          • 2011-02-15
          相关资源
          最近更新 更多