Skip to main content

Thread, Process, Goroutines: Definitions, How They Work, Differences, and Utility

1. Process

Definition:
A process is an independent program in execution, with its own memory space, code, data, and system resources.

How it works:

  • The operating system (OS) creates a process when you run a program.
  • Each process is isolated from others; it cannot directly access another process's memory.
  • Communication between processes (Inter-Process Communication, IPC) is possible but more complex (e.g., pipes, sockets).

Utility:

  • Used for running separate applications or services.
  • Good for isolation and security (a crash in one process doesn't affect others).

2. Thread

Definition:
A thread is the smallest unit of execution within a process. Multiple threads can exist within the same process, sharing the same memory and resources.

How it works:

  • Threads within the same process share code, data, and resources, but each has its own execution stack and program counter.
  • Threads are lighter than processes and can communicate more easily (since they share memory).
  • The OS schedules threads for execution, often on different CPU cores.

Utility:

  • Used for parallelism within a single application (e.g., handling multiple user requests, background tasks).
  • More efficient than processes for tasks that need to share data.

3. Goroutine

Definition:
A goroutine is a lightweight thread managed by the Go runtime (not the OS), used in the Go programming language.

How it works:

  • Goroutines are multiplexed onto a smaller number of OS threads by the Go runtime scheduler.
  • They are extremely lightweight (a few KB of stack space) and can be created in large numbers.
  • Communication and synchronization between goroutines are typically done using channels.

Utility:

  • Ideal for concurrent programming in Go (e.g., web servers, parallel computations).
  • Makes it easy to write scalable, concurrent code without worrying about OS thread management.

Key Differences

AspectProcessThreadGoroutine
MemorySeparate per processShared within processShared within process
Creation CostHighMediumVery Low
SchedulingBy OSBy OSBy Go runtime
CommunicationIPC (complex)Shared memory (easy)Channels (easy, safe)
Crash ImpactIsolatedCan affect processCan affect process
LanguageAnyAnyGo only

Summary of Utility

  • Processes: Use for strong isolation, running separate programs/services.
  • Threads: Use for parallelism within a program, sharing data easily.
  • Goroutines: Use in Go for massive concurrency with minimal overhead.

Deep Dive: Threads and Processes

Is a Process Always Made Up of Threads?

Short Answer:
Yes, in modern operating systems, every process has at least one thread.

Explanation

  • Single-threaded Process:

    • When a process is created, it starts with a single thread, often called the "main thread."
    • This thread executes the program's code.
    • If the program never creates additional threads, it remains a single-threaded process.
  • Multi-threaded Process:

    • A process can create additional threads to perform tasks concurrently.
    • All threads within a process share the same memory and resources.
  • Thread as the Execution Unit:

    • In modern OSes, a thread is the actual unit of execution.
    • Even if you don't explicitly create threads, the OS creates at least one thread for your process to run.

Historical Context

  • Older Systems:
    • In very old or simple operating systems, the concept of threads didn't exist. The process itself was the unit of execution.
    • Modern systems (Windows, Linux, macOS, etc.) always use threads, even if you don't see them directly.

Summary Table

ScenarioThreads Present?Notes
Modern OS, any processYes (at least 1)Main thread always exists
Multi-threaded programYes (many)Threads created for concurrency
Old/simple OSNo (historically)Process = execution unit, no thread concept

Key Point:

Every process in a modern OS has at least one thread (the main thread). Multi-threaded processes have more.


Deep Dive: Routines (Goroutines, Coroutines, Threads) and Core Utilization

What is a Routine?

  • "Routine" is a general term for a function or procedure. In concurrency, it often refers to goroutines (Go), coroutines (Python, Lua, Kotlin), or threads.

How Do Routines Work Behind the Scenes?

1. Goroutines (Go)

  • Managed by the Go runtime, not the OS.
  • When you start a goroutine, it's scheduled by the Go scheduler, which multiplexes many goroutines onto a smaller number of OS threads.
  • The Go runtime automatically manages the mapping of goroutines to OS threads and can move goroutines between threads as needed.
  • By default, Go will use as many OS threads as there are CPU cores (configurable with GOMAXPROCS).
  • The Go scheduler tries to keep all CPU cores busy by distributing goroutines across available threads/cores.
  • If you have many goroutines and multiple CPU cores, Go can run them in parallel, maximizing CPU utilization.

2. Coroutines (General, e.g., Python asyncio)

  • Coroutines are functions that can pause and resume their execution (using await, yield, etc.).
  • They are scheduled cooperatively, meaning they yield control back to the event loop, which then runs the next coroutine.
  • Coroutines are not OS threads; they run in a single thread unless you explicitly use threads or processes.
  • By default, coroutines run on a single OS thread and thus on a single CPU core.
  • To utilize multiple cores, you need to combine coroutines with multiprocessing or threading.

3. Threads (General)

  • Threads are managed by the OS.
  • Each thread can be scheduled on any available CPU core by the OS scheduler.
  • Multiple threads can run in parallel on multiple cores.
  • If you create multiple threads, the OS can run them on different CPU cores, allowing true parallelism (especially for CPU-bound tasks).

Summary Table

TypeManaged ByParallelismCore UtilizationNotes
GoroutineGo runtimeYesAcross multiple coresEfficient, lightweight, Go-specific
CoroutineLanguage/runtimeNo (by default)Single core (unless combined with threads/processes)Cooperative multitasking, not true parallelism
ThreadOSYesAcross multiple coresTrue parallelism, heavier than goroutines/coroutines

How the Process Works Behind the Scenes

  1. You start a routine (goroutine/coroutine/thread).
  2. Scheduler (OS or language runtime) decides when and where to run it.
  3. If multiple CPU cores are available:
    • Threads and goroutines can be run in parallel on different cores.
    • Coroutines (by default) run on one core unless you use multiple processes/threads.
  4. The scheduler balances the workload to maximize CPU utilization.

In summary:

  • Goroutines and threads can utilize multiple CPU cores for parallel execution.
  • Coroutines, by default, do not utilize multiple cores unless combined with other concurrency mechanisms.
  • The underlying scheduler (OS or language runtime) is responsible for distributing work across available cores.