A developer rewrites a single-threaded program to use 4 threads on a 4-core machine, expecting a 4x speedup. Instead, the program runs slower than before. What is the most likely explanation?
AThreads are inherently slower than single-threaded execution on all modern hardware
BSynchronization overhead and lock contention between threads eliminate the expected speedup
CUser-level threads cannot run on multiple cores, so only one core executes at a time
DThe OS scheduler can only assign one thread per process regardless of core count
Threads are not automatically faster — synchronization overhead is real and significant. If threads must frequently acquire and release locks to access shared data, they spend time waiting for each other rather than running in parallel. Lock contention can serialize execution almost as badly as a single-threaded program, while adding the overhead of thread management. Threads provide speedup only when work can be genuinely parallelized with minimal synchronization — identifying those workloads requires careful design.
Question 2 Multiple Choice
Thread A and Thread B both read a shared counter (value: 10), each increment it by 1, and write the result back. After both threads complete, what values are possible for the counter?
AAlways 12 — the OS ensures threads execute their operations atomically
BEither 11 or 12 — a race condition means one thread's write may overwrite the other's
CAlways 11 — the OS merges concurrent writes by taking the last value written
DThe program will always crash — concurrent writes to the same variable are undefined behavior
This is the classic race condition. If Thread A reads 10, Thread B also reads 10 (before A writes), then A writes 11 and B also writes 11, the counter ends at 11 despite two increments. If the threads happen to interleave perfectly (A reads, increments, writes, then B reads), the result is 12. The actual result depends on scheduling timing, which varies between runs — this is what makes race conditions notoriously difficult to debug. The fix is synchronization (a lock around the read-increment-write sequence).
Question 3 True / False
Threads within the same process can communicate by reading and writing shared variables directly, without any OS-mediated mechanism like pipes or sockets.
TTrue
FFalse
Answer: True
This is one of threads' key advantages over processes. Because threads share the process's address space — the same heap, global variables, and data segments — one thread can simply write to a variable and another can read it. No system call, no pipe setup, no serialization required. This makes thread communication extremely fast. The tradeoff is that this same sharing creates race conditions: any shared variable can be read and written simultaneously by multiple threads unless access is synchronized.
Question 4 True / False
User-level threads can fully utilize multiple CPU cores because the thread library manages their scheduling independently of the OS.
TTrue
FFalse
Answer: False
User-level threads are invisible to the OS kernel — the kernel sees only one process. Because the kernel schedules processes (not user threads) onto cores, it assigns at most one core to the process at any time. Worse, if any user thread makes a blocking system call (like reading from a file), the kernel blocks the entire process, suspending all user threads even though other threads could be running. Kernel threads, by contrast, are scheduled directly by the OS and can run on separate cores simultaneously, enabling true multi-core parallelism.
Question 5 Short Answer
Why is creating a new thread much cheaper than creating a new process, and what is the fundamental tradeoff of this efficiency?
Think about your answer, then reveal below.
Model answer: A new process requires the OS to allocate an entirely separate address space: new page tables, memory maps for code/heap/stack, and independent resource tracking. A new thread requires only its own stack and register set — everything else (address space, open files, heap) is inherited from the parent process with no copying. The tradeoff is that the shared address space removes isolation: all threads can accidentally or maliciously access each other's data, and a bug in one thread can corrupt state used by others. Processes pay a higher creation and context-switch cost in exchange for strong safety boundaries; threads pay a lower cost but require careful synchronization to avoid race conditions and data corruption.
The efficiency gain comes directly from what is not duplicated. The safety cost comes from what is shared. This tradeoff is the central design tension in concurrent programming.