DEV Community

Cover image for Concurrency Patterns 101
himank
himank

Posted on

Concurrency Patterns 101

Event loops and threads are two different concurrency patterns that can be used to manage multiple tasks simultaneously. Although both patterns achieve concurrency, they differ in the way they handle tasks and the underlying mechanisms used to manage concurrency. In this blog, I will explain the technical differences between event loops and threads.

Event Loop:
Photo by Tine Ivanič on Unsplash

An event loop is a pattern commonly used in non-blocking I/O applications, such as web servers and user interfaces. In an event loop, a single thread is used to process multiple events and requests by continually monitoring a queue of events and processing them in a non-blocking manner. The event loop is an efficient way of managing concurrency as it avoids creating new threads for each request, which can lead to excessive overheads and slow down the application.
Here’s an example of an event loop in Python:

import asyncio

async def coroutine():
   print(“Starting coroutine”)
   await asyncio.sleep(1)
   print(“Coroutine finished”)

loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine())
Enter fullscreen mode Exit fullscreen mode

In this example, we use the asyncio library to create an event loop. The coroutine() function is an asynchronous function that will be executed by the event loop. The run_until_complete() method is used to run the event loop until the coroutine() function has completed its execution.
Another example of an event loop is JavaScript’s event loop. The JavaScript event loop is used in web applications to manage events such as user input and network requests. Here’s an example of how the JavaScript event loop works:

console.log("Start");

setTimeout(() => {
 console.log(“First”);
}, 2000);

setTimeout(() => {
 console.log("Second");
}, 1000);

console.log("End");
Enter fullscreen mode Exit fullscreen mode

In this example, the console.log() statements are executed synchronously, followed by two asynchronous setTimeout() calls. The first setTimeout() is set to execute after two seconds, while the second setTimeout() is set to execute after one second. The event loop in JavaScript continuously monitors the queue of events and executes the callbacks associated with the setTimeout() calls when their time is up.

Threads:
Photo by Stephane Gagnon on Unsplash

Threads are a pattern commonly used in applications that require heavy computation or I/O operations. In a threaded application, multiple threads are used to execute tasks concurrently, and the operating system’s scheduler manages the threads’ execution. Threads can perform tasks simultaneously, leading to improved performance, but can also lead to synchronization and deadlock issues.
Here’s an example of a threaded application in Python:

import threading

def print_numbers():
   for i in range(1, 11):
   print(i)

def print_letters():
   for i in range(ord('a'), ord('k')):
   print(chr(i))
t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_letters)
t1.start()
t2.start()
t1.join()
t2.join()
Enter fullscreen mode Exit fullscreen mode

In this example, we use the threading library to create two threads, t1 and t2. Each thread performs a different task, printing numbers and letters, respectively. The start() method is used to start the execution of the threads, and the join() method is used to wait for the threads to complete their execution.
Another example of a threaded application is a web server that creates a new thread for each incoming request. Each thread handles a single request, and the operating system’s scheduler manages the threads’ execution.

Difference:

The main technical difference between event loops and threads is the way they handle concurrency.
In an event loop, all tasks are executed in a non-blocking manner, meaning that when a task is waiting for I/O or another task to complete, the event loop can continue to process other tasks. This makes event loops very efficient in managing concurrency, as they avoid the overhead of creating and managing multiple threads.
However, event loops may not be suitable for applications that require heavy computation, as long-running tasks can block the event loop and slow down the application.
In contrast, threads are well-suited for applications that require heavy computation or I/O operations. They also require synchronization and coordination to avoid race conditions and deadlock issues. Additionally, creating and managing threads can be expensive, leading to higher overheads and sometimes decreased performance.

In summary, event loops and threads are two different concurrency patterns that can be used to manage multiple tasks simultaneously. Each pattern has its advantages and disadvantages, and the choice of concurrency pattern depends on the application’s specific requirements.
Originally published at medium

Top comments (0)