在 Linux 中何时使用 pthread_exit() 以及何时使用 pthread_join()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20824229/
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
When to use pthread_exit() and when to use pthread_join() in Linux?
提问by dexterous
I am new to pthreads, and I am trying to understand it. I saw some examples like the following.
我是 pthreads 的新手,我正在努力理解它。我看到了一些像下面这样的例子。
I could see that the main()
is blocked by the API pthread_exit()
, and I have seen examples where the main function is blocked by the API pthread_join()
. I am not able to understand when to use what?
我可以看到main()
API 阻止了pthread_exit()
,并且我看到了主函数被 API 阻止的示例pthread_join()
。我无法理解何时使用什么?
I am referring to the following site - https://computing.llnl.gov/tutorials/pthreads/. I am not able to get the concept of when to use pthread_join()
and when to use pthread_exit()
.
我指的是以下站点 - https://computing.llnl.gov/tutorials/pthreads/。我无法获得何时使用pthread_join()
以及何时使用的概念pthread_exit()
。
Can somebody please explain? Also, a good tutorial link for pthreads will be appreciated.
有人可以解释一下吗?此外,一个很好的 pthreads 教程链接将不胜感激。
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
Realized one more thing i.e.
实现了一件事,即
pthread_cancel(thread);
pthread_join(thread, NULL);
Sometimes, you want to cancel the thread while it is executing. You could do this using pthread_cancel(thread);. However, remember that you need to enable pthread cancel support. Also, a clean up code upon cancellation.
有时,您想在线程执行时取消它。您可以使用 pthread_cancel(thread); 执行此操作。但是,请记住,您需要启用 pthread 取消支持。此外,取消时的清理代码。
thread_cleanup_push(my_thread_cleanup_handler, resources);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
static void my_thread_cleanup_handler(void *arg)
{
// free
// close, fclose
}
采纳答案by Suvarna Pattayil
As explained in the openpub documentations,
如 openpub 文档中所述,
pthread_exit()
will exit the thread that calls it.
pthread_exit()
将退出调用它的线程。
In your case since the main calls it, main threadwill terminate whereas your spawned threads will continue to execute. This is mostly used in cases where the main thread is only required to spawn threads and leave the threads to do their job
在您的情况下,由于 main 调用它,主线程将终止,而您生成的线程将继续执行。这主要用于主线程只需要生成线程并让线程完成其工作的情况
pthread_join
will suspend execution of the thread that has called it unless the target thread terminates
pthread_join
将挂起调用它的线程的执行,除非目标线程终止
This is useful in cases when you want to wait for thread/s to terminate before further processing in main thread.
当您想在主线程中进一步处理之前等待线程终止时,这很有用。
回答by Alok Save
pthread_exit
terminates the calling thread while pthread_join
suspends execution of calling thread until target threads completes execution.
pthread_exit
终止调用线程,同时pthread_join
挂起调用线程的执行,直到目标线程完成执行。
They are pretty much well explained in detail in the open group documentation:
它们在开放组文档中得到了很好的解释:
回答by Basile Starynkevitch
You don't need any calls to pthread_exit(3)
in your particular code.
您不需要pthread_exit(3)
在特定代码中调用。
In general, the main
thread should notcall pthread_exit
, but should often call pthread_join(3)
to waitfor some other thread to finish.
一般情况下,main
线程应该不叫pthread_exit
,但应经常打电话pthread_join(3)
来等待某些其他线程结束。
In your PrintHello
function, you don't need to call pthread_exit
because it is implicit after returning from it.
在您的PrintHello
函数中,您不需要调用,pthread_exit
因为从它返回后它是隐式的。
So your code should rather be:
所以你的代码应该是:
void *PrintHello(void *threadid) {
long tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
return threadid;
}
int main (int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
intptr_t t;
// create all the threads
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", (long) t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) { fprintf(stderr, "failed to create thread #%ld - %s\n",
(long)t, strerror(rc));
exit(EXIT_FAILURE);
};
}
pthread_yield(); // useful to give other threads more chance to run
// join all the threads
for(t=0; t<NUM_THREADS; t++){
printf("In main: joining thread #%ld\n", (long) t);
rc = pthread_join(&threads[t], NULL);
if (rc) { fprintf(stderr, "failed to join thread #%ld - %s\n",
(long)t, strerror(rc));
exit(EXIT_FAILURE);
}
}
}
回答by Jens Gustedt
Both methods ensure that your processdoesn't end before all of your threads have ended.
这两种方法都确保您的进程不会在所有线程结束之前结束。
The join method has your thread of the main
function explicitly wait for all threads that are to be "joined".
join 方法让您的main
函数线程显式等待所有要“加入”的线程。
The pthread_exit
method terminates your main
function and thread in a controlled way. main
has the particularity that ending main
otherwise would be terminating your whole process including all other threads.
该pthread_exit
方法main
以受控方式终止您的函数和线程。main
具有特殊性,main
否则结束将终止您的整个过程,包括所有其他线程。
For this to work, you have to be sure that none of your threads is using local variables that are declared inside them main
function. The advantage of that method is that your main
doesn't have to know all threads that have been started in your process, e.g because other threads have themselves created new threads that main
doesn't know anything about.
为此,您必须确保没有任何线程使用在它们的main
函数内部声明的局部变量。该方法的优点是您main
不必知道进程中已启动的所有线程,例如因为其他线程自己创建了main
不知道任何信息的新线程。
回答by jim mcnamara
Hmm.
唔。
POSIX pthread_exit
description from http://pubs.opengroup.org/onlinepubs/009604599/functions/pthread_exit.html:
POSIX pthread_exit
来自http://pubs.opengroup.org/onlinepubs/009604599/functions/pthread_exit.html 的描述:
After a thread has terminated, the result of access to local (auto) variables of the thread is
undefined. Thus, references to local variables of the exiting thread should not be used for
the pthread_exit() value_ptr parameter value.
Which seems contrary to the idea that local main() thread variables will remain accessible.
这似乎与本地 main() 线程变量将保持可访问的想法相反。
回答by MichaelGoren
The pthread_exit() API
pthread_exit() API
as has been already remarked, is used for the calling thread termination. After a call to that function a complicating clean up mechanism is started. When it completes the thread is terminated. The pthread_exit() API is also called implicitly when a call to the return() routine occurs in a thread created by pthread_create(). Actually, a call to return() and a call to pthread_exit() have the same impact, being called from a thread created by pthread_create().
如前所述,用于调用线程终止。调用该函数后,将启动复杂的清理机制。当它完成时,线程终止。当 pthread_create() 创建的线程中发生对 return() 例程的调用时,也会隐式调用 pthread_exit() API。实际上,调用 return() 和调用 pthread_exit() 具有相同的影响,都是从 pthread_create() 创建的线程调用的。
It is very important to distinguish the initial thread, implicitly created when the main() function starts, and threads created by pthread_create(). A call to the return() routine from the main() function implicitly invokes the exit() system call and the entire process terminates. No thread clean up mechanism is started. A call to the pthread_exit() from the main() function causes the clean up mechanism to start and when it finishes its work the initial thread terminates.
区分初始线程(在 main() 函数启动时隐式创建)和 pthread_create() 创建的线程非常重要。从 main() 函数调用 return() 例程会隐式调用 exit() 系统调用,并且整个过程终止。没有启动线程清理机制。从 main() 函数调用 pthread_exit() 会导致清理机制启动,当它完成其工作时,初始线程终止。
What happens to the entire process (and to other threads) when pthread_exit() is called from the main() function depends on the PTHREAD implementation. For example, on IBM OS/400 implementation the entire process is terminated, including other threads, when pthread_exit() is called from the main() function. Other systems may behave differently. On most modern Linux machines a call to pthread_exit() from the initial thread does not terminate the entire process until all threads termination. Be careful using pthread_exit() from main(), if you want to write a portable application.
当从 main() 函数调用 pthread_exit() 时,整个进程(以及其他线程)会发生什么取决于 PTHREAD 实现。例如,在 IBM OS/400 实现上,当从 main() 函数调用 pthread_exit() 时,整个进程包括其他线程都将终止。其他系统的行为可能有所不同。在大多数现代 Linux 机器上,从初始线程调用 pthread_exit() 不会终止整个进程,直到所有线程终止。 如果您想编写可移植的应用程序,请小心使用 main() 中的 pthread_exit()。
The pthread_join() API
pthread_join() API
is a convenient way to wait for a thread termination. You may write your own function that waits for a thread termination, perhaps more suitable to your application, instead of using pthread_join(). For example, it can be a function based on waiting on conditional variables.
是一种等待线程终止的便捷方式。您可以编写自己的等待线程终止的函数,这可能更适合您的应用程序,而不是使用 pthread_join()。例如,它可以是一个基于等待条件变量的函数。
I would recommend for reading a book of David R. Butenhof “Programming with POSIX Threads”.It explains the discussed topics (and more complicated things) very well (although some implementation details, such as pthread_exit usage in the main function, not always reflected in the book).
我建议阅读David R. Butenhof的书“使用 POSIX 线程编程”。它很好地解释了所讨论的主题(以及更复杂的事情)(尽管一些实现细节,例如 main 函数中的 pthread_exit 用法,并不总是反映在书中)。
回答by Abhitesh khatri
pthread_exit()
will terminate the calling thread and exit from that(but resources used by calling thread is not released to operating system if it is not detached from main thread.)
pthread_exit()
将终止调用线程并从中退出(但如果调用线程未从主线程分离,则调用线程使用的资源不会释放到操作系统。)
pthrade_join()
will wait or block the calling thread until target thread is not terminated.
In simple word it will wait for to exit the target thread.
pthrade_join()
将等待或阻塞调用线程,直到目标线程未终止。简而言之,它将等待退出目标线程。
In your code, if you put sleep(or delay) in PrintHello
function before pthread_exit()
, then main thread may be exit and terminate full process, Although your PrintHello
function is not completed it will terminate. If you use pthrade_join()
function in main before calling pthread_exit()
from main it will block main thread and wait to complete your calling thread (PrintHello
).
在您的代码中,如果您在PrintHello
函数 before 中放入睡眠(或延迟)pthread_exit()
,则主线程可能会退出并终止整个进程,尽管您的PrintHello
函数未完成,但它会终止。如果pthrade_join()
在pthread_exit()
从 main调用之前在 main 中使用函数,它将阻塞主线程并等待完成调用线程 ( PrintHello
)。
回答by Preeti
Using pthread_exit
in the main thread(in place of pthread_join
), will leave the main thread in defunct(zombie) state. Since not using pthread_join
, other joinable threads which are terminated will also remain in the zombie state and cause resource leakage.
使用pthread_exit
在主线程(代替pthread_join
),将离开主线程中倒闭(僵尸)的状态。由于没有使用pthread_join
,其他被终止的joinable线程也会保持僵尸状态,造成资源泄漏。
Failure to join with a thread that is joinable (i.e., one that is not detached), produces a "zombie thread". Avoid doing this, since each zombie thread consumes some system resources, and when enough zombie threads have accumulated, it will no longer be possible to create new threads (or processes).
与可连接的线程(即未分离的线程)连接失败,会产生“僵尸线程”。避免这样做,因为每个僵尸线程都会消耗一些系统资源,并且当积累了足够的僵尸线程时,将不再可能创建新的线程(或进程)。
Another point is keeping the main thread in the defunct state, while other threads are running may cause implementation dependent issues in various conditions like if resources are allocated in main thread or variables which are local to the main thread are used in other threads.
另一点是保持主线程处于失效状态,而其他线程正在运行可能会在各种情况下导致实现相关的问题,例如在主线程中分配资源或在其他线程中使用主线程本地的变量。
Also, all the shared resources are released only when the process exits, it's not saving any resources. So, I think using pthread_exit
in place of pthread_join
should be avoided.
而且,所有共享资源只有在进程退出时才会释放,并不节省任何资源。所以,我认为应该避免使用pthread_exit
代替pthread_join
。
回答by Gregg Wonderly
When pthread_exit() is called, the calling threads stack is no longer addressable as "active" memory for any other thread. The .data, .text and .bss parts of "static" memory allocations are still available to all other threads. Thus, if you need to pass some memory value into pthread_exit() for some other pthread_join() caller to see, it needs to be "available" for the thread calling pthread_join() to use. It should be allocated with malloc()/new, allocated on the pthread_join threads stack, 1) a stack value which the pthread_join caller passed to pthread_create or otherwise made available to the thread calling pthread_exit(), or 2) a static .bss allocated value.
调用 pthread_exit() 时,调用线程堆栈不再可作为任何其他线程的“活动”内存进行寻址。“静态”内存分配的 .data、.text 和 .bss 部分仍可用于所有其他线程。因此,如果您需要将一些内存值传递给 pthread_exit() 以供其他 pthread_join() 调用者查看,则它需要“可用”以供调用 pthread_join() 的线程使用。它应该使用 malloc()/new 分配,分配在 pthread_join 线程堆栈上,1) pthread_join 调用者传递给 pthread_create 或以其他方式提供给调用 pthread_exit() 的线程的堆栈值,或 2) 分配的静态 .bss价值。
It's vital to understand how memory is managed between a threads stack, and values store in .data/.bss memory sections which are used to store process wide values.
了解如何在线程堆栈之间管理内存以及值存储在用于存储进程范围值的 .data/.bss 内存部分中是至关重要的。