Linux 是否存在无效的 pthread_t id?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6276939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there an invalid pthread_t id?
提问by shodanex
I would like to call pthread_join for a given thread id, but only if that thread has been started. The safe solution might be to add a variable to track which thread where started or not. However, I wonder if checking pthread_t variables is possible, something like the following code.
我想为给定的线程 id 调用 pthread_join,但前提是该线程已启动。安全的解决方案可能是添加一个变量来跟踪哪个线程启动与否。但是,我想知道是否可以检查 pthread_t 变量,类似于以下代码。
pthread_t thr1 = some_invalid_value; //0 ?
pthread_t thr2 = some_invalid_value;
/* thread 1 and 2 are strated or not depending on various condition */
....
/* cleanup */
if(thr1 != some_invalid_value)
pthread_join(&thr1);
if(thr2 != some_invalid_value)
pthread_join(&thr2);
Where some_invalid_value could be 0, or an implementation dependant 'PTHREAD_INVALID_ID' macro
some_invalid_value 可以是 0,或者依赖于实现的 'PTHREAD_INVALID_ID' 宏
PS : My assumption is that pthread_t types are comparable and assignable, assumption based on
PS:我的假设是 pthread_t 类型是可比较和可分配的,假设基于
PPS : I wanted to do this, because I thought calling pthread_join on invalid thread id was undefinde behaviour. It is not. However, joining a previously joined thread IS undefined behaviour. Now let's assume the above "function" is called repeatedly. Unconditionnally calling pthread_join and checking the result might result in calling pthread_join on a previously joined thread.
PPS:我想这样做,因为我认为在无效线程 id 上调用 pthread_join 是不确定的行为。它不是。但是,加入先前加入的线程是未定义的行为。现在让我们假设上面的“函数”被重复调用。无条件调用 pthread_join 并检查结果可能会导致在先前加入的线程上调用 pthread_join。
采纳答案by qbert220
Your assumption is incorrect to start with. pthread_t objects are opaque. You cannot compare pthread_t types directly in C. You should use pthread_equal instead.
你的假设一开始就不正确。pthread_t 对象是不透明的。您不能直接在 C 中比较 pthread_t 类型。您应该改用 pthread_equal。
Another consideration is that if pthread_create fails, the contents of your pthread_t will be undefined. It may not be set to your invalid value any more.
另一个考虑是,如果 pthread_create 失败,则 pthread_t 的内容将是未定义的。它可能不再设置为您的无效值。
My preference is to keep the return values of the pthread_create calls (along with the thread IDs) and use that to determine whether each thread was started correctly.
我的偏好是保留 pthread_create 调用的返回值(以及线程 ID)并使用它来确定每个线程是否正确启动。
回答by Mat
As suggested by Tony, you can use pthread_self()
in this situation.
正如托尼所建议的,您可以pthread_self()
在这种情况下使用。
But do notcompare thread_t
s using ==
or !=
. Use pthread_equal
.
但不要thread_t
使用==
or比较s !=
。使用pthread_equal
.
From the pthread_self
man page:
从pthread_self
手册页:
Therefore, variables of type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3) instead.
因此,pthread_t 类型的变量不能使用 C 相等运算符 (==) 进行可移植的比较;请改用 pthread_equal(3)。
回答by HavePoopWillStep
Unfortunately, on systems where pthread_t
is a pointer, pthread_equal()
can return equality even though the two args refer to different threads, e.g. a thread can exit and a new thread can be created with the same pthread_t
pointer value.
不幸的是,在pthread_t
一个指针的系统上,pthread_equal()
即使两个 args 引用不同的线程,也可以返回相等,例如,一个线程可以退出,并且可以使用相同的pthread_t
指针值创建一个新线程。
回答by It'sPete
I recently ran into this same issue. If pthread_create() failed, I ended up with a undefined, invalid value stored in my phtread_t structure. As a result, I keep a boolean associated with each thread that gets set to true if pthread_create() succeeded.
我最近遇到了同样的问题。如果 pthread_create() 失败,我最终会在我的 phtread_t 结构中存储一个未定义的无效值。因此,如果 pthread_create() 成功,我会保留一个与每个线程关联的布尔值,该布尔值设置为 true。
Then all I need to do is:
然后我需要做的就是:
void* status;
if (my_thread_running) {
pthread_join(thread, &status);
my_thread_running = false;
}
回答by breakpoint
This is an excellent question that I really wish would get more discussion in C++ classes and code tests.
这是一个很好的问题,我真的希望能在 C++ 类和代码测试中得到更多讨论。
One option for some systems-- which may seem like overkill to you, but has come in handy for me-- is to start a thread which does nothing other than efficiently wait for a tear-down signal, then quit. This thread stays running for the life of the application, going down very late in the shutdown sequence. Until that point, the ID of this thread can effectively be used as an "invalid thread" value-- or, more likely, as an "uninitialized" sentinel-- for most purposes. For example, my debug libraries typically track the threads from which mutexes were locked. This requires initialization of that tracking value to something sensible. Because POSIX rather stupidly declined to require that platforms define an INVALID_THREAD_ID, and because my libraries allow main() to lock things (making the pthread_self checks that are a good solution pthread_create unusable for lock tracking), this is the solution I have come to use. It works on any platform.
某些系统的一种选择——这对你来说似乎有点矫枉过正,但对我来说已经派上用场了——是启动一个线程,它除了有效地等待拆卸信号之外什么都不做,然后退出。该线程在应用程序的整个生命周期内保持运行,在关闭序列中非常晚关闭。在那之前,该线程的 ID 可以有效地用作“无效线程”值——或者,更有可能,用作“未初始化”哨兵——用于大多数目的。例如,我的调试库通常会跟踪锁定互斥锁的线程。这需要将该跟踪值初始化为合理的值。因为 POSIX 相当愚蠢地拒绝要求平台定义 INVALID_THREAD_ID,并且因为我的库允许 main() 锁定事物(使 pthread_self 检查是一个很好的解决方案 pthread_create 无法用于锁定跟踪),这是我开始使用的解决方案。它适用于任何平台。
Note, however, that you have a little more design work to do if you want this to be able to initialize static thread references to invalid values.
但是请注意,如果您希望它能够将静态线程引用初始化为无效值,那么您需要做更多的设计工作。
回答by Mark Lakata
I was porting some code that used pthreads into a C++ application, and I had the same question. I decided it was easier to switch to the C++ std::thread
object, which has the .joinable()
method to decide whether or not to join, i.e.
我正在将一些使用 pthreads 的代码移植到 C++ 应用程序中,我遇到了同样的问题。我决定切换到C++std::thread
对象更容易,它有.joinable()
决定是否加入的方法,即
if (t.joinable()) t.join();
I found that just calling pthead_join
on a bad pthread_t value (as a result of pthread_create
failing) caused a seg fault, not just an error return value.
我发现仅仅调用pthead_join
错误的 pthread_t 值(由于pthread_create
失败)会导致段错误,而不仅仅是错误返回值。