After reading up on this answer and \"Linux Kernel Development\" by Robert Love and, subsequently, on the clone() system call, I discovered that processes and t
Imagine some sort of "meta-entity". If the entity shares none of the resources (address space, file descriptors, etc) of its parent then it's a process, and if the entity shares all of the resources of its parent then it's a thread. You could even have something half-way between process and thread (e.g. some resources shared and some not shared). Take a look at the "clone()" system call (e.g. http://linux.die.net/man/2/clone ) and you'll see this is how Linux does things internally.
Now hide that behind some sort of abstraction that makes everything look like either a process or a thread. If the abstraction is flawless you'd never know the difference between "entities" and "processes and threads". The abstraction isn't quite flawless though - the PID you're seeing is actually an "entity ID".
On Linux, every thread gets a thread ID. The thread ID of the main thread serves double duty as the process ID (and is rather well-known in the user interface). The thread ID is an implementation detail of Linux, and unrelated to the POSIX ID. For more details, refer to the gettid system call (not available from pure Python since it's system-specific).
These confusions all stem from the fact that the kernel developers originally held an irrational and wrong view that threads could be implemented almost entirely in userspace using kernel processes as the primitive, as long as the kernel offered a way to make them share memory and file descriptors. This lead to the notoriously bad LinuxThreads implementation of POSIX threads, which was rather a misnomer because it did not give anything remotely resembling POSIX thread semantics. Eventually LinuxThreads was replaced (by NPTL), but a lot of the confusing terminology and misunderstandings persist.
The first and most important thing to realize is that "PID" means different things in kernel space and user space. What the kernel calls PIDs are actually kernel-level thread ids (often called TIDs), not to be confused with pthread_t which is a separate identifier. Each thread on the system, whether in the same process or a different one, has a unique TID (or "PID" in the kernel's terminology).
What's considered a PID in the POSIX sense of "process", on the other hand, is called a "thread group ID" or "TGID" in the kernel. Each process consists of one or more threads (kernel processes) each with their own TID (kernel PID), but all sharing the same TGID, which is equal to the TID (kernel PID) of the initial thread in which main runs.
When top shows you threads, it's showing TIDs (kernel PIDs), not PIDs (kernel TGIDs), and this is why each thread has a separate one.
With the advent of NPTL, most system calls that take a PID argument or act on the calling process were changed to treat the PID as a TGID and act on the whole "thread group" (POSIX process).