Sign in to unlock

Get unlimited access to all questions and answers


Get lifetime access


Track progress


Save time

21 Concurrency interview questions and answers for software engineers

In computer science, concurrency is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order, without affecting the final outcome. Here is a list of coding interview questions on Concurrency to help you get ready for your next data structures interview in 2021.

  • 1.

    What is a Deadlock?


    Deadlock is a state of a computer system where two or more processes are unable to proceed because each is waiting for one or more others to release a resource. It is a type of livelock where multiple processes or threads are caught in a circular chain of needing resources that they cannot release.

    Core Characteristics

    1. Mutual Exclusion: At least one resource must be held exclusively (non-sharable) in a manner that if one process is using it, then another process must wait for the first one to release the resource.

    2. Hold and Wait: Processes already holding resources can request additional resources and are waiting for them to be satisfied.

    3. No Preemption: Resources cannot be forcibly removed from a process.

    4. Circular Wait: There is a chain of processes wherein each process is holding a resource that is requested by the next process in the chain.

    Code Example: Simulating Deadlock in Python

    In the following Python code, two threads are trying to acquire two locks in opposite order. This creates a situation where both threads are holding one lock each and waiting for the lock held by the other thread.

    import threading
    # Resource A and B represented by Lock objects
    lock_a = threading.Lock()
    lock_b = threading.Lock()
    # Function executed by Thread 1
    def thread_1():
        print("Thread 1: Acquired both locks")
    # Function executed by Thread 2
    def thread_2():
        lock_a.acquire()  # Causes the deadlock
        print("Thread 2: Acquired both locks")
    # Create and start both threads
    t1 = threading.Thread(target=thread_1)
    t2 = threading.Thread(target=thread_2)

    This code will result in a deadlock, where both threads are indefinitely waiting for the lock held by the other thread, thus unable to proceed.

    Strategies for Deadlock Prevention and Recovery

    Deadlock Prevention Strategies

    1. Mutual Exclusion Avoidance: Ensure that resources can be shared instead of being held exclusively.

    2. Hold and Wait Avoidance: Acquire all resources a process will need before it starts execution.

    3. No Preemption Strategy: Allow resources to be preempted from processes.

    4. Circular Wait Avoidance: Order resources and request them in the same order.

    Deadlock Recovery Strategies

    1. Process Termination: Abort one or more processes involved in the deadlock.

    2. Resource Preemption: Preempt resources from one or more processes and give them to others.

    3. Rollback: Rollback the actions of one or more processes to a previous checkpoint and restart them.

    Deadlock in Real-World Scenarios

    • Database Management: When a transaction holds a lock on a data item and tries to lock another item, it may go into a deadlock condition.

    • Interlocking Train Tracks: If two trains are moving toward each other on different tracks and there is a switch malfunction, a deadlock can occur.

  • 2.

    Explain the difference between Asynchronous and Parallel programming?


    Both Asynchronous and Parallel programming aim to improve program execution, but they do so in different ways and for different purposes.

    • Asynchronous programming: Primarily used to manage the efficiency of a single task by allowing it to "yield" to other tasks, without blocking the main execution thread until it completes.
    • Parallel programming: Used to perform multiple tasks simultaneously, with the goal of utilizing multiple computing resources to speed up the overall process.

    Key Differences

    Execution Context

    • Asynchronous Programming:
      • Within a single thread.
      • Uses features like event loops and callbacks.
    • Parallel Programming:
      • Can utilize multiple threads, processes, or machines.
      • Often managed through specialized libraries or APIs, like concurrent.futures in Python.

    Resource Utilization

    • Asynchronous Programming:
      • Well-suited for tasks that are I/O-intensive, like network operations or file downloads.
      • Allows the CPU to work on other tasks while waiting for I/O to complete.
    • Parallel Programming:
      • Benefits CPU-bound tasks, like complex mathematical computations.
      • Can improve speed by maximizing CPU resources.


    • Asynchronous Programming:
      • Often requires complex callback chains or the use of more modern, easy-to-use constructs like Python's asyncio.
    • Parallel Programming:
      • More complex to implement, especially when dealing with shared resources or race conditions.

    Real-World Examples

    Asynchronous Programming

    • Web Servers: Asynchronous server frameworks like asgi in Python are often used to serve web requests efficiently.
    • Web Scraping: Async libraries like aiohttp in Python can be used to scrape websites in a non-blocking manner.

    Parallel Programming

    • Machine Learning: Libraries like TensorFlow can utilize multiple GPUs for faster model training.
    • Data Processing Pipelines: Tools like Apache Spark distribute computational tasks across a cluster of machines for faster data processing.

    Code Example: Asynchronous Programming in Python

    Here's a simple Python code snippet that demonstrates the concept of asynchronous programming using Python's asyncio library:

    import asyncio
    async def perform_task(task_name):
        print(f'Starting task: {task_name}')
        await asyncio.sleep(1)
        print(f'Completed task: {task_name}')
    # The event loop
    async def main():
        tasks = [
            asyncio.ensure_future(perform_task('Task 1')),
            asyncio.ensure_future(perform_task('Task 2')),
        await asyncio.gather(*tasks)
    # Run the main program
    if __name__ == '__main__':
        loop = asyncio.get_event_loop()

    In this example, the functions perform_task() are tasks that are executed asynchronously in the main() function using asyncio. Each task simulates work by sleeping for 1 second.

  • 3.

    What is a Mutex?


    A Mutex (short for mutual exclusion) is a synchronization primitive commonly used in multi-threaded and multi-process applications to prevent more than one thread or process from entering a critical section of code (a user-defined portion of code that should not run concurrently by multiple threads or processes for data integrity or consistency reasons). It is a special type of lock that can be acquired and owned by only one thread at a time. When a thread acquires a Mutex, other threads attempting to acquire it will be blocked until the Mutex is released by the owning thread.

    Why Do We Need Mutexes?

    In a multi-threaded or multi-process environment, race conditions can occur when two or more threads or processes access shared data or resources simultaneously, and at least one of them tries to modify it. This can lead to data corruption, inconsistency, and other bugs that are hard to debug, detect, and fix.

    Mutexes serve as a guard for these critical sections, ensuring that only one thread executes a particular piece of code at a time, thereby avoiding race conditions and maintaining data integrity.

    Features of Mutex

    • Mutual Exclusion: Ensures that only one thread or process can own the Mutex at any given time.
    • Ownership: The thread that has acquired the Mutex is the only one that can release it.
    • Blocking: If a second thread tries to acquire a Mutex that is already locked, it will be blocked until the Mutex is released.

    How Does a Mutex Work?

    When a thread wants to enter a critical section, it tries to acquire the Mutex. There are generally two possible scenarios:

    1. If the Mutex is unlocked, meaning no other thread owns it, the thread that wants to enter the critical section acquires the Mutex and proceeds with its work.
    2. If the Mutex is locked, the thread that wants to acquire it will be blocked (i.e., it will be made to wait) until it can obtain ownership.

    Once the thread that owns the Mutex has completed its work in the critical section, it releases the Mutex, thereby making it available for other threads to acquire.

    Mutex Implementations

    The mechanics of Mutex implementation can vary across programming languages and operating systems, but the core idea remains the same: to allow exclusive access to a resource. Some common Mutex types are:

    • Binary Mutex: Can be in two states only; locked or unlocked.
    • Counting Mutex: Can have a count greater than one, allowing nested acquisitions.
    • Recursive Mutex: Special type of counting Mutex that allows the same thread to acquire it multiple times.

    Mutex vs. Semaphore

    A Mutex is often compared to a Semaphore, another popular synchronization primitive. While both serve to control access to a shared resource, the primary difference lies in their capabilities:

    • Mutual Exclusion vs. Resource Synchronization: Mutexes are typically used to serialize concurrent access to a shared resource, while Semaphores can also be used for more complex synchronization patterns.
    • Binary vs. Counting: Mutexes are generally binary, whereas Semaphores can maintain a count and allow multiple threads to enter a critical section.
One tip that got me hired by Google, Microsoft, and Stripe

I've worked for Microsoft, Google, Stripe, and received offers from many other companies. One thing I learned when I was interviewing myself is that standard interview tips are woefully inadequate.

Reverse Tech Interview: Questions to Stump an Interviewer

Few people want to get into an uncomfortable environment or an unprofitable company with no prospects. If you’re wondering how to get a real feel for a company during an interview, you’re welcome. I’ll give a list of questions that interviewers don’t usually expect...

How to become a programmer, move to the US, and get a dream job

Are you curious about what you need to do to earn more than $15.000 a month, drive a Tesla, live in sunny California, and work at Google, Apple, Facebook, or Amazon?

11 Reactive Systems interview questions and answers for software engineers

Reactive systems are an architectural style that allows multiple individual applications to blend into one unit, reacting to their environment, while staying aware of each other. Here is a list of coding interview questions on Reactive Systems to help you get ready for your next data struc...

. Reactive Systems
34 Microservices interview questions and answers for software engineers

Microservice architecture – a variant of the service-oriented architecture structural style – arranges an application as a collection of loosely coupled services. In a microservices architecture, services are fine-grained and the protocols are lightweight. Here is a list of coding intervie...

. Microservices
7 Layering & Middleware interview questions for developers

Middleware in the context of distributed applications is software that provides services beyond those provided by the operating system to enable the various components of a distributed system to communicate and manage data. Middleware supports and simplifies complex distributed application...

. Layering & Middleware
55 Docker interview questions and answers for software engineers

Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. Here is a list of coding interview questions on Docker to help you get ready for your next data structures interview in 2021.

. Docker
23 Databases interview questions and answers for software engineers

A database is an organized collection of data, generally stored and accessed electronically from a computer system. Where databases are more complex they are often developed using formal design and modeling techniques. Here is a list of coding interview questions on Databases to help you g...

. Databases
21 Concurrency interview questions and answers for software engineers

In computer science, concurrency is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order, without affecting the final outcome. Here is a list of coding interview questions on Concurrency to help you get ready for your n...

. Concurrency
13 CAP Theorem interview questions and answers for software engineers

In theoretical computer science, the CAP theorem, also named Brewer's theorem after computer scientist Eric Brewer, states that it is impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees: Consistency: Every read receives the ...

. CAP Theorem
Load more posts


folder icon

Access all answers

Get the inside track on what to expect in your next tech interview. We offer you a collection of high quality technical interview questions to help you prepare for your next coding interview.

graph icon

Track progress

A smart interface helps you track your progress and focus on the topics you need. You can search through questions or sort them by difficulty or type.

clock icon

Save time

Save tens of hours searching for information on hundreds of low-quality sites designed to drive traffic and make money from advertising.

Land a six-figure job at one of the top companies.

amazon logo facebook logo google logo microsoft logo uber logo
Prepare for a technical interview

Get hired with our
tech interview questions & answers