Threads vs processes vs async interview questions

7 operating systems interview questions on threads, processes and async, each with the correct answer and a full explanation.

A CPU bound job (pure computation, no I/O) runs on an 8 core machine. Which approach gives near linear speedup in a runtime without a global interpreter lock?
Show answer

Answer

About 8 workers (threads or processes), one per core
CPU bound work scales with cores, so one worker per core keeps every core busy with minimal switching. Hundreds of threads add switching and cache pressure with no extra cores to run on. An event loop runs on one core and only helps when tasks wait on I/O. Context switching costs little at 8 workers on 8 cores.

Source: IGotAnOffer: Anthropic software engineer interview, OSTEP: Concurrency: An Introduction

A service makes 5000 concurrent outbound HTTP calls that mostly wait on the network. Which model fits best?
Show answer

Answer

Async I/O on an event loop, or a pool of many lightweight threads
I/O bound work spends its time waiting, so the goal is cheap concurrency, not more CPU. An event loop with epoll or many cheap threads handles thousands of waits. A process per call costs megabytes each and fork overhead. One thread per core caps in flight requests at the core count. Busy polling burns CPU doing nothing.

Source: OSTEP: Event-based Concurrency, The C10K problem

In an async server, one handler calls a blocking database driver (no await) that takes 2 seconds. What happens to other requests?
Show answer

Answer

All of them stall for 2 seconds, because the event loop thread is blocked
An event loop runs handlers on one thread and switches only at await points. A blocking call never yields, so nothing else runs until it returns. Offload it to a thread pool or use an async driver. The others assume preemption the loop does not do. Most loops have no automatic offload or default handler timeout.

Source: OSTEP: Event-based Concurrency, IGotAnOffer: Anthropic software engineer interview

A service runs untrusted native plugins as threads inside one process. One plugin segfaults. What happens, and what would running each plugin as its own process change?
Show answer

Answer

The segfault kills the whole process with every plugin; as separate processes only the faulty plugin dies
Threads share one address space, so a fatal signal from memory corruption kills every thread in the process. Separate processes have separate address spaces, which is why browsers and servers use process isolation. Thread isolation is the common misconception. Processes do not share memory unless they set it up explicitly.

Source: OSTEP: Concurrency: An Introduction, fork(2), Linux manual page

A multithreaded server calls fork() while another thread holds an application mutex, and the child then tries to lock that mutex before exec. What can happen?
Show answer

Answer

The child deadlocks, because only the forking thread exists in the child and the mutex stays locked forever
fork copies the whole address space but only the calling thread, so a mutex held by another thread is copied in the locked state with no owner left to release it. POSIX limits the child to async signal safe calls until exec. glibc special cases its own malloc locks around fork, but no library does that for your mutexes. All threads being copied is the common wrong belief. The kernel knows nothing about user space locks. The mutex is a byte for byte copy of the parent's, locked state included.

Source: fork(2), Linux manual page, glibc source: posix/fork.c

A runtime multiplexes 100k lightweight tasks (goroutines, virtual threads) over a few OS threads. Which statement is true?
Show answer

Answer

Tasks are cheap to create and block, but CPU parallelism is still limited by the number of OS threads and cores
Lightweight tasks make concurrency cheap: small stacks and user space switching, with blocking calls parked on the runtime's poller. Parallel CPU work is still capped by cores. Tasks on different OS threads race on shared memory exactly like threads, so locks or channels are still needed. Modern runtimes park the task on I/O instead of stalling the OS thread, though some calls (pinned or native) can still block a carrier.

Source: The C10K problem, OSTEP: Concurrency: An Introduction

A job is 90% parallelizable and 10% strictly serial. What is the best possible speedup with unlimited cores?
Show answer

Answer

10x
Amdahl's law: speedup is at most 1 / serial fraction, here 1 / 0.1 = 10. Even infinite cores cannot shrink the serial 10%. 90x confuses the percentage with a speedup factor. Unlimited ignores the serial part. 9x would be the bound for about 11% serial.

Source: OSTEP: Concurrency: An Introduction

These questions come from the Operating Systems Interview Practice pack in Bertopia.

More operating systems topics

Practise these on your commute