我想为给定的线程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);
其中some_invalid_value可能为0,或者实现依赖于'PTHREAD_INVALID_ID'宏
PS: 我的假设是pthread_t类型具有可比性和可分配性,基于
的假设PPS: 我想这样做,因为我认为在无效的线程id上调用pthread_join是未定义的行为。它不是。但是,加入以前加入的线程是未定义的行为。现在让我们假设重复调用上面的“函数”。 无条件地调用pthread_join并检查结果可能会导致在先前连接的线程上调用pthread_join。
答案 0 :(得分:17)
您的假设不正确。 pthread_t对象是不透明的。您无法直接在C中比较pthread_t类型。您应该使用pthread_equal。
另一个考虑因素是如果pthread_create失败,pthread_t的内容将是未定义的。它可能不再设置为无效值。
我的首选是保留pthread_create调用的返回值(以及线程ID),并使用它来确定每个线程是否正确启动。
答案 1 :(得分:11)
根据Tony的建议,您可以在这种情况下使用pthread_self()
。
但不使用thread_t
或==
来比较!=
。使用pthread_equal
。
来自pthread_self
手册页:
因此,pthread_t类型的变量不能使用C等于运算符(==)进行可比较的比较;改为使用pthread_equal(3)。
答案 2 :(得分:1)
不幸的是,在pthread_t
是指针的系统上,pthread_equal()
可以返回相等,即使两个args引用不同的线程,例如线程可以退出,并且可以使用相同的pthread_t
指针值创建新线程。
答案 3 :(得分:1)
我最近遇到了同样的问题。如果pthread_create()失败,我最终会在我的phtread_t结构中存储一个未定义的无效值。因此,如果pthread_create()成功,我会保持与每个线程关联的布尔值设置为true。
然后我需要做的就是:
void* status;
if (my_thread_running) {
pthread_join(thread, &status);
my_thread_running = false;
}
答案 4 :(得分:0)
This is an excellent question that I really wish would get more discussion in C++ classes and code tests.
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.
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.
答案 5 :(得分:0)
我正在将一些使用pthreads的代码移植到C ++应用程序中,并且我有同样的问题。我认为切换到C ++ std::thread
对象比较容易,该对象具有.joinable()
方法来决定是否加入,即
if (t.joinable()) t.join();
我发现仅对错误的pthread_t值调用pthead_join
(由于pthread_create
失败)会导致段错误,而不仅仅是错误返回值。