What is Concurrency?

Learn about concurrency in general.

Concurrency

Concurrency means the simultaneous and independent execution of multiple processes. Thanks to concurrency, when two or more threads share or access the same resource, they don’t lead to race conditions, deadlock, or other similar problems. Because of concurrency, independent calculations can be performed in any sequence to produce the same result.

In single-core hardware, we can achieve concurrency using context switching. In multicore hardware, we can achieve concurrency using parallelism.

Understand concurrency with an example

Let’s take the example of booking a ticket to understand concurrency.

function{
seat = 1
thread_one{
if ( seat > 0 ){
book_ticket();
seat--;
}
}
thread_two{
if ( seat > 0 ){
book_ticket();
seat--;
}
}
}

Let’s suppose we have a multicore processor. In our processor, thread_one is running on core 1, thread_two is running on core 2, and only one seat is available.

Let’s explore different possible scenarios.

In the first scenario, since both threads are executing independently on different cores, the first thread executes completely and updates the available seats. The number of seats is zero, so the second thread can’t book the ticket. It’s not guaranteed that the cores will execute in the same format every time.

Note: Before executing on the hardware, the compiler converts the code into low-level code. We may write several atomic statements, but combining multiple atomic statements won’t lead to an atomic code block.

Let’s take another scenario where the code executes in a different format.

​​In this case, only one statement is executing at a time. Both threads check the available seats, which are greater than zero. As a result, both the threads book the tickets.

A third scenario could also happen. In this scenario, before updating the seats, both threads check their if conditions and both book the seats.

The important thing is that we can’t determine which statement will execute at what time. The same thing can happen with single-core hardware as well.

Concurrency in Golang

Concurrency in Golang# In general, we use threads to execute tasks in parallel. The same concepts can be applied in any other language, but in Golang, concurrency is a feature of the language itself. The other programming languages that provide parallelism and concurrency don’t support those as a feature. They use kernel threads to do the work, and the system handles the kernel threads. Working with kernel threads—including the creation of threads, destruction of threads, context switching, and changing the value of registers—is a very costly operation. To get our work done, we have to interrupt the system.

Golang uses a different concept. It uses goroutines, which are independent of each other, to run things in parallel.

Golang has the following built-in concurrency constructs:

In Golang, there are different concepts. It uses goroutines, which are independent of each other, to run things in parallel.

Golang has the following built-in concurrency constructs:

  • Goroutines: Goroutines are functions executing concurrently with other goroutines in the same thread or set of threads. It runs independently of the function or goroutine from which it starts. Goroutine works in the background at all times and is like the & in shell scripting.

  • Channels: A channel is a pipeline for sending and receiving data to communicate between goroutines.

  • Select: The select clause chooses one out of several communications. In other words, out of all the ready-to-execute case statements, the clause will randomly select any one of them. If none of the cases is ready to execute, the select clause will look for a default, and if the default isn’t present, it will be blocked.