Abstract


More Performant

Threads avoid the need for expensive context switching, making them 10-100 times faster than processes.

They are also faster to create and destroy compared to processes because they do not require a System Call (系统调用) to the underlying Kernel.

Easier to program

Unlike processes, different parts of a program can communicate without using Interrupts (中断) or Inter-Process Communication, making threads easier to work with.

Lack of protection between threads

Threads within the same process can access each other’s stack, potentially leading to issues like one thread overwriting another’s data. This lack of isolation can cause the entire process to fail.

Forking

When forking a process, should all threads be copied, or just the main one?

Interrupt Handling

For handling Software Interrupt, which thread should manage it?

Thread ID

  • In Linux, each thread is treated as a process, so each has its own process ID. This allows the kernel to treat threads and processes in the same way

Thread group ID

All threads in the same process share the same thread group ID (TGID), which is the PID of the main thread of the process. User-space tools like ps and top often only show the TGID by default.

A TGID is handy as it allows the kernel to apply operations, such as signals, that apply to all threads of the same process.

Blocking Thread

  • Also known as Synchronized Threads
  • A Thread remains idle while waiting for IO Operations or Network Operations, etc.
  • This is straightforward to implement and understand!

Thread Table


Thread Interleaving


int x = 0;
void thread1() {
    x += 1; // Operation 1
    x *= 2; // Operation 2
}
void thread2() {
    x += 3; // Operation 3
    x *= 4; // Operation 4
}
 
// Sequential Execution
x = 0 → x + 1 = 1 → x * 2 = 2 → x + 3 = 5 → x * 4 = 20
 
// Interleaved Execution
x = 0 → x + 3 = 3 (Operation 3)
      → x + 1 = 4 (Operation 1)
      → x * 4 = 16 (Operation 4)
      → x * 2 = 32 (Operation 2)

Important

Since threads often share resources (e.g., memory, variables, or files), the order in which their instructions are executed can affect the outcome of a program.

The non-deterministic nature of thread interleaving makes bugs hard to reproduce and debug.

It can lead to problems like race conditions if not handled carefully with synchronisation techniques.

PThread


pthread_yield()

Unlike processes, threads within the same program can collaborate to fulfil a particular feature, which is why functions like pthread_yield() exist to allow threads to hand over execution to other threads.