Multi-threading and  Parallel Programming
Tags: programming, multithreading, java, productivity
Published: 2021-02-05 07:34:20

Multi-threading is a widespread programming and execution model that allows multiple threads to exist within the context of one process. Each of these threads can run in parallel and these thread share similar address space. Okay let's start from the very beginning.

###What is a Thread?
A `thread` of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system. Most times a thread exist within the process and multiple threads can exist within a single process, hence multi-threading.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pwtqtgnrq62dh5n6io8a.PNG)

> I'd say a Computer Scientist would see A `Thread` the same way a Chemist would see an An `Atom` .

These `threads` run concurrently and they share resources. The implementation of `threads` and processes differ between operating systems, but in most cases a thread is a component of a process.

###What is a Process?
Processes are instances of programs which typically run independent from each other. For Example, if you start a Java program the operating system spawns a new `process` which runs in parallel to other programs. Inside those processes we can utilize threads to execute code concurrently, so we can make the most out of the available cores of the CPU.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cudzw6gzhi20es4l3nvg.PNG)

Unlike Threads, processes do not share resource with one another. A `process` is a unit of resources, while a thread is a unit of scheduling and execution.

###Thread Pool
Creating a brand-new OS thread requires memory allocation and CPU instructions in order to set it up and also kill it down. In order to better handle the usage of a thread and also avoid the creation of new ones, the operating systems or platforms reckon with a `Thread Pool` feature, which allows the application to take an already existing thread to use.

That’s a much more efficient way to handle multiple threads without dealing with its creation or destruction. Furthermore, the OSs know when a thread from the thread pool is not actively in use thus, they can automatically “skip” it during the threads’ iteration.

###Descriptive Programming Representations Of Threads
We'd take a look at threads as implemented from two classes in Java, `Executors` and `Runnable`.

* **Executors**  
`Executors` as a class in Java that abstracts most of the manual thread creation process. They are capable of running asynchronous tasks and typically manage a pool of threads, so we don't have to create new threads manually.

The class `Executors` provides convenient factory methods for creating different kinds of executor services. In the sample below we use an executor with a thread pool of size one.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5hbjoi52xqi9rw6osdwy.PNG)

The result looks similar to the above sample but when running the code you'll notice an important difference, the java process never stops! `Executors` have to be stopped explicitly - otherwise they keep listening for new tasks.

An `ExecutorService` provides two methods for that purpose: `shutdown()` waits for currently running tasks to finish while `shutdownNow()` interrupts all running tasks and shut the executor down immediately. This service is mostly used when working with socket connections, to facilitate asynchronous calls(Sink-Source connections). 

* **Runnable**
A `Runnable` is functional interface defining a single void no-arguments method `run()`. Before starting a new thread you have to specify the code to be executed by this thread, often called the task and this is done by implementing a `Runnable`. Note that, you can have as many tasks as possible.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/z8r4h7b8gjhbt7ga4k4y.PNG)

For the example above, we utilize Java 8 lambda expressions to print the current threads name to the console. First we execute the runnable directly on the main thread before starting a new thread. See the sample outputs below.

```
Hello main
Hello Thread-0
Done!
```
*Or that:*
```
Hello main
Done!
Hello Thread-0
```
We have two possible outputs because due to concurrent execution we cannot predict if the runnable will be invoked before or after printing `Done`. The order is non-deterministic, thus making concurrent programming a complex task in larger applications. Although Threads can also be put to sleep for a certain duration.

###Multi-threading in-depth
Like we've clearly stated earlier, A `multi-threaded` program contains two or more parts that can run concurrently and each part can handle a different task at the same time making optimal use of the available resources specially when your computer has multiple CPUs. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/b9a62hzkm6gjaxff5e9g.PNG)

`Multi-threading` extends the idea of multitasking into applications where you can subdivide specific operations within a single application into individual threads. It enables you to write in a way where multiple activities can proceed concurrently in the same program.

There are a handful of programming languages that give room for `multi-threading`, and most of the languages are Object Oriented Programming languages(OOP). Languages like `Java`, `C`,`C++` and even `.NET` frameworks. Some other interpreted languages also made the cut, like `Ruby MRI` for `Ruby` and `CPython` for `Python`. If you were waiting to see `Javascript`, well you won't because JavaScript does not support multi-threading and that's because the `JavaScript` interpreter in the browser is a single thread.

###Heavily Multi-threaded Applications
Almost all well-built applications support multi-threading. Let's look at browsers. Most browsers are multi-threaded from `firefox` to `Safari` to `Chrome` and many others. But today we'd talk more about `Chrome`.

**Google Chrome**
Chrome has a multi-process architecture and each process is heavily multi-threaded. The main goal is to keep the main thread (“UI” thread in the browser process) and IO thread (each process’ thread for handling IPC) responsive. This means offloading any blocking I/O or other expensive operations to other threads.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gp3ddpyezcuqmmomh349.PNG)

In `Chrome`, each and every tab you open gets its own content process. Five tabs, 5 processes, one hundred tabs, 100 processes. This approach maximizes performance, but you pay a hefty penalty in memory consumption and battery life. Ever wondered why the CPU consumption for Chrome on your task manager is always high? Well, here you go.

Every chrome process has, 
* A `main thread`
 This thread updates the UI and runs most of Blink.
* An `IO thread`
 This thread handles IPCs and network requests
* A few more `special-purpose threads`.
* A pool of `general-purpose threads`. 

**Chrome Compared to Firefox**
While `Chrome` creates a content process for each tab, `Firefox` instead spins up to four content process threads by default. In Firefox, the first 4 tabs each use those 4 processes and additional tabs then use threads within those processes. Multiple tabs within a process share the browser engine that already exists in memory, instead of each creating their own.

{% twitter 1357400668835823617 %}

###Threads Vs Processes
Threads are different from the conventional multitasking process in so many ways:
* Processes are typically independent, while threads exist as subsets of a process.
* Processes carry considerably more state information than threads, whereas multiple threads within a process share process state as well as memory and other resources.
* Processes have separate address spaces, whereas threads share their address space.
* Processes interact only through system-provided inter-process communication mechanisms.
* Context switching between threads in the same process typically occurs faster than context switching between processes.

###Parallelism
Parallelism relate to the concept were the work is distributed in multiple units, in such a way that it doesn't compromise the final product but minimizing the total execution time.

Parallel execution is the ability of two (or more) tasks to run at the very same time. While Concurrency stands for the possibility, Parallelism is the reality.

###Conclusion
Multithreading is now an important part of modern software development. It’s supported by many programming languages and platforms and goes all the way down to the operating system. Knowing how to work with multiple threads can definitely lead developers to build better applications.