Back 2 BaseCS : OS : Thread Pools

Kshitij Agrawal
Back 2 baseCS
Published in
3 min readAug 8, 2024

ThreadPool & Wolverine ..

Think of a city fraught with criminals, and every once in a while — one of the criminal does the bad thing that criminals do. Every time a bad thing is being done, wolverine needs to go and save the good folks. Now what happens if there are multiple bad things going on — we need more wolverines. But we don’t need to get new wolverine every time a crime happens — we just need enough of them to be able to handle the crime happening at a given moment. We need a pool of wolverines!

A pool of wolverines

Jokes aside, This is the concept behind Thread Pools. Writing multicore applications is not easy. Developers really need to learn complicated thread management and scheduling. That’s why over time, this task (no pun intended) was deemed easier to be delegated to OS, system libraries, or runtimes like .NET. These systems maintain and nurture a pool of threads, so we developers can focus on ‘tasks’ — what tasks can be run in parallel, and forget about what thread are they executed on.

The pattern of using pools is a more general one. In addition to threads, there are connection pools for TCP connections. There are virtual machine pools for handling incoming calls to your web service. There are worker pools to pick up queued up work. Your city has a pool of policeman, and the support team has a pool of support personnel.

Why not just create threads on the fly? Well, creating threads is certainly better than forking new processes, but still not the cheapest thing to do. Also, we can’t just spawn infinite threads on a machine — we only have so many cores and so much memory. The overhead of having too many threads will soon hurt performance more than the concurrency benefits.

Thread pools work with a queue mechanism. Work can be queued or ‘submitted’ to be picked up by threads. When a thread is free, it will pick up the work and execute it. After execution, the freed up thread is now returned to the pool again.

Why Use Thread Pools?

  1. Efficiency: Creating and destroying threads for each task is costly in terms of time and system resources. Thread pools mitigate this by reusing existing threads.
  2. Performance: Faster to reuse an existing thread than creating a new one.
  3. Scalability: Thread pools can handle a large number of tasks efficiently, making them ideal for scalable applications.
  4. Resource Management: Thread pools prevent resource exhaustion by limiting the number of concurrent threads, protecting the system from being overwhelmed.

Sophisticated thread pools these days can actually scale up and down the number of threads in the thread pool, and adapt to your application performance requirements.

.NET Thread pool

In .NET, thread pools are a built-in feature for managing concurrent tasks. .NET uses thread pool threads for many purposes, including Task Parallel Library (TPL) operations, asynchronous I/O completion, timer callbacks, asynchronous method calls using delegates, and System.Net socket connections.

When you use Tasks and async/await — you are automatically using the thread pool threads. Note that these threads are ‘background’ threads — that is they do not block your app process shutdown. The opposite of background threads are ‘foreground’ threads — they keep your exe running.

You can read more about the .net thread pool here.

In coming days and months, we will dig deeper into each of the OS components and learn concepts and implementations. If you are interested to learn these and up-level your computer engineering skills, please consider subscribing to this newsletter.

If you loved this piece, please consider leaving a small tip to keep me motivated! Your support means a lot!

--

--

Kshitij Agrawal
Back 2 baseCS

Director Of Engineering @ Microsoft Azure | IIT Roorkee