This answer suggest -pthread
is preferable to -lpthread
because predefined macros.
Empirically, -pthread
gives me only one extra macro: #define _REENTRANT 1
and it also appears to force libpthread.so.0
as a dynamic linktime dependency.
When I compile with -lpthread
, that dependency is only added if I actually call any of the pthread
functions.
This is preferably to me, because then I wouldn't have to treat multithreaded programs differently in my build scripts.
So my question is, what else is there to -pthread
vs -lpthread
and is it possible to use use -pthread
without forcing said dynamic linktime dependency?
Demonstration:
$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread
$ echo 'int main(){ return pthread_self(); }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000)
$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -pthread && ldd a.out | grep pthread
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000)
The idea that you should use GCC's special option
-pthread
instead of-lpthread
is outdated by probably some decade and a half (with respect to glibc, that is). In modern glibc, the switch to threading is entirely dynamic, based on whether the pthreads library is linked or not. Nothing in the glibc headers changes its behavior based on whether_REENTRANT
is defined.As an example of the dynamic switching, consider
FILE *
streams. Certain operations on streams are locking, likeputc
. Whether you're compiling a single-threaded program or not, it calls the sameputc
function; it is not re-routed by the preprocessor to a "pthread-aware"putc
. What happens is that do-nothing stub functions are used to go through the motions of locking and unlocking. These functions get overridden to real ones when the threading library is linked in.I just did a cursory
grep
through the include file tree of a glibc installation. Infeatures.h
,_REENTRANT
causes__USE_REENTRANT
to be defined. In turn, exactly one thing seems to depend on whether__USE_REENTRANT
is present, but has a parallel condition which also enables it. Namely, in<unistd.h>
there is this:This looks dubious and is obsolete; I can't find it in the master branch of the glibc git repo.
And, oh look, just mere days ago (December 6) a commit was made on this topic:
https://sourceware.org/git/?p=glibc.git;a=commit;h=c03073774f915fe7841c2b551fe304544143470f
Among the changes:
See? :)