Threads provided by the operating system 29 Threads provided by the operating system Note! We call this 1:1 threading. Each task is assigned one OS thread. Since this book will not focus specifically on OS threads as a way to handle concurrency going forward, we treat them more thoroughly here. Let's start with the obvious. To use threads provided by the operating system, you need, well, an operating system. Before we discuss the use of threads as a means to handle concurrency, we need to be clear about what kind of operating systems we're talking about since they come in different flavors. Embedded systems are more widespread now than ever before. This kind of hardware might not have the resources for an operating system, and if they do, you might use a radically different kind of operating system tailored to your needs, as the systems tend to be less general purpose and more specialized in nature. Their support for threads, and the characteristics of how they schedule them, might be different from what you're used to in operating systems such as Windows or Linux. Since covering all the different designs is a book on its own, we'll limit the scope to talk about treads, as they're used in Windows and Linux-based systems running on popular desktop and server CPUs. OS threads are simple to implement and simple to use. We simply let the OS take care of everything for us. We do this by spawning a new OS thread for each task we want to accomplish and write code as we normally would. The runtime we use to handle concurrency for us is the operating system itself. In addition to these advantages, you get parallelism for free. However, there are also some drawbacks and complexities resulting from directly managing parallelism and shared resources. Creating new threads takes time Creating a new OS thread involves some bookkeeping and initialization overhead, so while switching between two existing threads in the same process is pretty fast, creating new ones and discarding ones you don't use anymore involves work that takes time. All the extra work will limit throughput if a system needs to create and discard a lot of them. This can be a problem if you have huge amounts of small tasks that need to be handled concurrently, which often is the case when dealing with a lot of I/O. Each thread has its own stack We'll cover stacks in detail later in this book, but for now, it's enough to know that they occupy a fixed size of memory. Each OS thread comes with its own stack, and even though many systems allow this size 