Search code examples
multithreadingprocessoperating-systemcpu

Does a CPU process always have at least one thread?


I am aware that threads are used for multitasking and they are lightweight.

Let's say I need a process without any multitasking. If I just create a process, will the CPU associate a single thread to the process OR will it execute the process alone without need to have a thread?


Solution

  • Well, that depends on the OS that you're talking about but, for many, the creation of a process includes the act of creating a single thread for that process.

    That thread is then free to go and create other threads belonging to the process.

    It makes little sense to talk about a process with no threads since that means no code is running for that process so it can't really do anything useful. And one of the things it won't be able to do is create the first thread for that process if you want it to do any useful work :-)


    As an example, in the Linux kernel, the creation of a process is little different to creating a new thread. That's because the kernel schedules threads rather than processes.

    Processes are now considered to be groups of threads with the same thread group ID (TGID), that TGID being the thread ID (TID) of the first thread created for that process.

    When you fork or vfork or clone (without CLONE_THREAD), you get a new thread with a new TID and the TGID is set to that TID - that's a new process.

    When you clone with CLONE_THREAD, you get a new thread with a new TID but the TGID remains the same as your cloner. That's a different thread in the same process.

    That's how Linux (as an example) distinguishes between processes and threads without having to make the scheduler too complicated. The scheduler can choose to ignore thread groups entirely if it wishes. It's actually incredibly clever.

    To code that exists outside of the scheduler, a group of threads with the same TGID is considered a process (with the TGID being what that code sees as the process ID).

    This includes both user space code and other bits of the kernel since, for example, how threads are grouped into processes has a bearing on things like signal delivery and exit codes.