为什么 pthread_join 不采用线程指针?
Why does pthread_join not take a thread pointer?
非常不言自明的问题。例如,pthread_create 的 header 显示它需要一个指向线程的指针:
int WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);
好的,有道理,您在内存中分配一个 pthread,然后将指针传递给 pthread_create,这样它就被初始化了……但是现在查看 header 的 pthread_join:
int WINPTHREAD_API pthread_join(pthread_t t, void **res);
它需要 pthread_t 的副本。我只是不明白为什么它不接受指向已经存在的线程的指针,而不是复制它并传递它;似乎如果有的话,这样做会导致更多问题和更多内存使用。我错过了什么吗?我阅读了联机帮助页,它似乎没有为此提供原因。
It takes a copy of the pthread_t
.
是的。
I just don't get why it doesn't take
a pointer to that already existing thread,
pthread_t
是线程 标识符。规范始终以这种方式引用它。复制它不会复制线程本身,也不会消耗比 pthread_t
占用更多的内存。
rather than copying it and
passing it over; it seems like if anything, doing so would cause more
problems and more memory use.
它不一定会导致更多的内存使用,因为 pthread_t
不一定比指针大。它可能是一个指针,或者一个整数。然而,即使它是一个结构,也没有理由认为它太大以至于按值传递它会带来严重的问题,因为细节在 pthreads 实现的控制之下。为什么实施者会那样搬起石头砸自己的脚?请注意,按值传递结构本质上并不比传递指针效率低。
至于内存使用过多以外的问题,您必须更具体一些,但我没有看到直接访问线程标识符的副本有任何固有问题vs.间接访问公共标识符对象,用于那些按值接受 pthread_t
的函数。
Am I missing something?
我怀疑您的担忧与对类型 pthread_t
的误解有关,因为它以某种方式携带支持线程操作的数据,而不是简单地识别线程。
您可能还假设 pthreads 是一个具有特定实现的库,而实际上,它首先是一个 规范 ,旨在提供多种实现。这是定义抽象数据类型 pthread_t
而不是指定 int
或 struct something *
的部分原因——实现可以选择要使用的实际类型。
也许您也过于关注 API 函数。即使在某些特定的实现中,将 pthread_t
按值传递给 pthread_join()
的效率低于将指针传递给一个指针的效率,您认为这实际上会产生多大的影响? pthread_join()
很少被调用,只有在调用者准备阻塞的情况下才会调用。如果参数传递比其他方式消耗的时间多几纳秒,这有什么关系?
I read the
manpage, it doesn't seem to offer a reason to this.
很少有手册页提供功能设计的基本原理,但我认为最可能的解释本质上是形式服从功能。那些按值接收 pthread_t
的函数这样做是因为它们不需要或不想修改调用者的值。这些功能的设计反映了这一点。
A pthread_t
是一个标识线程的小对象。它可以是一个指针、整数或者一个微小的结构。 pthread_t
实际上不是线程本身,就像 Win32 中的 HWND
对象不是 window 本身一样。
pthread_create
函数returns这个标识符通过一个指针指针,因为它已经returns一个int
类型的值用于错误指示。其他函数按值取 pthread_t
。
例如,要比较两个 pthread_t
对象是否引用同一个线程,您应该使用 pthread_equal
,它有两个 pthread_t
参数。有可能这个函数所做的只是使用 ==
比较两个值,但直接这样做可移植性差。如果 pthread_t
恰好是一个小结构,它甚至不会编译。
需要注意的一件事是 pthread 是 C API。与具有构造函数的 C++ 不同,复制 C 变量可以保证相当便宜。最坏的情况是一个大型结构的类型,但即便如此,它也只是一个 memcpy。这与 C++ 不同,后者的副本可以调用任意昂贵的构造函数。
非常不言自明的问题。例如,pthread_create 的 header 显示它需要一个指向线程的指针:
int WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);
好的,有道理,您在内存中分配一个 pthread,然后将指针传递给 pthread_create,这样它就被初始化了……但是现在查看 header 的 pthread_join:
int WINPTHREAD_API pthread_join(pthread_t t, void **res);
它需要 pthread_t 的副本。我只是不明白为什么它不接受指向已经存在的线程的指针,而不是复制它并传递它;似乎如果有的话,这样做会导致更多问题和更多内存使用。我错过了什么吗?我阅读了联机帮助页,它似乎没有为此提供原因。
It takes a copy of the
pthread_t
.
是的。
I just don't get why it doesn't take a pointer to that already existing thread,
pthread_t
是线程 标识符。规范始终以这种方式引用它。复制它不会复制线程本身,也不会消耗比 pthread_t
占用更多的内存。
rather than copying it and passing it over; it seems like if anything, doing so would cause more problems and more memory use.
它不一定会导致更多的内存使用,因为 pthread_t
不一定比指针大。它可能是一个指针,或者一个整数。然而,即使它是一个结构,也没有理由认为它太大以至于按值传递它会带来严重的问题,因为细节在 pthreads 实现的控制之下。为什么实施者会那样搬起石头砸自己的脚?请注意,按值传递结构本质上并不比传递指针效率低。
至于内存使用过多以外的问题,您必须更具体一些,但我没有看到直接访问线程标识符的副本有任何固有问题vs.间接访问公共标识符对象,用于那些按值接受 pthread_t
的函数。
Am I missing something?
我怀疑您的担忧与对类型 pthread_t
的误解有关,因为它以某种方式携带支持线程操作的数据,而不是简单地识别线程。
您可能还假设 pthreads 是一个具有特定实现的库,而实际上,它首先是一个 规范 ,旨在提供多种实现。这是定义抽象数据类型 pthread_t
而不是指定 int
或 struct something *
的部分原因——实现可以选择要使用的实际类型。
也许您也过于关注 API 函数。即使在某些特定的实现中,将 pthread_t
按值传递给 pthread_join()
的效率低于将指针传递给一个指针的效率,您认为这实际上会产生多大的影响? pthread_join()
很少被调用,只有在调用者准备阻塞的情况下才会调用。如果参数传递比其他方式消耗的时间多几纳秒,这有什么关系?
I read the manpage, it doesn't seem to offer a reason to this.
很少有手册页提供功能设计的基本原理,但我认为最可能的解释本质上是形式服从功能。那些按值接收 pthread_t
的函数这样做是因为它们不需要或不想修改调用者的值。这些功能的设计反映了这一点。
A pthread_t
是一个标识线程的小对象。它可以是一个指针、整数或者一个微小的结构。 pthread_t
实际上不是线程本身,就像 Win32 中的 HWND
对象不是 window 本身一样。
pthread_create
函数returns这个标识符通过一个指针指针,因为它已经returns一个int
类型的值用于错误指示。其他函数按值取 pthread_t
。
例如,要比较两个 pthread_t
对象是否引用同一个线程,您应该使用 pthread_equal
,它有两个 pthread_t
参数。有可能这个函数所做的只是使用 ==
比较两个值,但直接这样做可移植性差。如果 pthread_t
恰好是一个小结构,它甚至不会编译。
需要注意的一件事是 pthread 是 C API。与具有构造函数的 C++ 不同,复制 C 变量可以保证相当便宜。最坏的情况是一个大型结构的类型,但即便如此,它也只是一个 memcpy。这与 C++ 不同,后者的副本可以调用任意昂贵的构造函数。