Concurrency Interview Questions and Answers
Practice Concurrency interview questions and answers organized by difficulty, with revealable explanations and related topics.
Junior questions
3 questions- Question 1Junior
Explain the difference between Asynchronous and Parallel programming?
- Concurrency
Reveal answerHide answer
When you run something asynchronously it means it is non-blocking, you execute it without waiting for it to complete and carry on with other things. Parallelism means to run multiple things at the same time, in parallel. Parallelism works well when you can separate tasks into independent pieces of work. Async and Callbacks are generally a way (tool or mechanism) to express concurrency i.e. a set of entities possibly talking to each other and sharing resources. Take for example rendering frames of a 3D animation. To render the animation takes a long time so if you were to launch that render from within your animation editing software you would make sure it was runningasynchronously so it didn't lock up your UI and you could continue doing other things. Now, each frame of that animation can also be considered as an individual task. If we have multiple CPUs/Cores or multiple machines available, we can render multiple frames in parallel to speed up the overall workload.
- Question 2Junior
What is a Mutex?
- Concurrency
Reveal answerHide answer
A Mutex is a mutually exclusive flag. It acts as a gate keeper to synchronise two threads. When you have two threads attempting to access a single resource, the general pattern is to have the first block of code attempting access, to set the mutex before entering the code. When the second code block attempts access, it sees that themutex is set and waits until the first block of code is complete (and un-sets the mutex), then continues. Specific details of how this is accomplished obviously varies greatly by programming language.
- Question 3Junior
What is a Deadlock?
- Concurrency
Reveal answerHide answer
A lock occurs when multiple processes try to access the same resource at the same time. One process loses out and must wait for the other to finish. A deadlock occurs when the waiting process is still holding on to another resource that the first needs before it can finish.
So, an example: Resource A and resource B are used by process X and process Y X starts to use A. X and Y try to start using B Y 'wins' and gets B first now Y needs to use A A is locked by X, which is waiting for Y Thread 1 Thread 2
Lock1->Lock(); Lock2->Lock(); WaitForLock2(); WaitForLock1(); <-- Oops!The best way to avoid deadlocks is to avoid having processes cross over in this way. Reduce the need to lock anything as much as you can. In databases avoid making lots of changes to different tables in a single transaction, avoid triggers and switch to optimistic/dirty/nolock reads as much as possible.
Mid questions
7 questions- Question 1Mid
What is a Race Condition?
- Concurrency
Reveal answerHide answer
A race condition is a situation on concurrent programming where two concurrent threads or processes compete for a resource and the resulting final state depends on who gets the resource first. Because the thread scheduling algorithm can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data. Therefore, the result of the change in data is dependent on the thread scheduling algorithm, i.e. both threads are "racing" to access/change the data. Problems often occur when one thread does a "check-then-act" (e.g. "check" if the value is X, then "act" to do something that depends on the value being X) and another thread does something to the value in between the "check" and the "act". E.g:
if (x == 5) // The "Check" { y = x * 2; // The "Act" // If another thread changed x in between "if (x == 5)" and "y = x * 2" above, // y will not be equal to 10. }The point being, y could be 10, or it could be anything, depending on whether another thread changed x in between the check and act. You have no real way of knowing. In order to prevent race conditions from occurring, you would typically put a lock (Mutex or Semaphores) around the shared data to ensure only one thread can access the data at a time. This would mean something like this:
// Obtain lock for x if (x == 5) { y = x * 2; // Now, nothing can change x until the lock is released. // Therefore y = 10 } // release lock for x - Question 2Mid
How much work should I place inside a lock statement?
- Concurrency
Reveal answerHide answer
It is first and foremost a question of correctness. You should not care so much about efficiency trade-offs, but more about correctness. Do as little work as possible while locking a particular object. Locks that are held for a long time are subject to contention, and contention is slow. Note that this implies that the total amount of code in a particular lock
and the total amount of code in all lock statements that lock on the same object are both relevant. Have as few locks as possible, to make the likelihood of deadlocks (or livelocks) lower. If you want concurrency, use processes as your unit of concurrency. If you cannot use processes then use application domains. If you cannot use application domains, then have your threads managed by the Task Parallel Library and write your code in terms of high-level tasks (jobs) rather than low-level threads (workers). Benchmarking and being aware that there are more options than "lock everything everywhere" and "lock only the bare minimum".
- Question 4Mid
What is a Race Condition?
- Concurrency
Reveal answerHide answer
A race condition is a situation on concurrent programming where two concurrent threads or processes compete for a resource and the resulting final state depends on who gets the resource first. Because the thread scheduling algorithm can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data. Therefore, the result of the change in data is dependent on the thread scheduling algorithm, i.e. both threads are "racing" to access/change the data. Problems often occur when one thread does a "check-then-act" (e.g. "check" if the value is X, then "act" to do something that depends on the value being X) and another thread does something to the value in between the "check" and the "act". E.g:
if (x == 5) // The "Check" { y = x * 2; // The "Act" // If another thread changed x in between "if (x == 5)" and "y = x * 2" above, // y will not be equal to 10. }The point being, y could be 10, or it could be anything, depending on whether another thread changed x in between the check and act. You have no real way of knowing. In order to prevent race conditions from occurring, you would typically put a lock (Mutex or Semaphores) around the shared data to ensure only one thread can access the data at a time. This would mean something like this:
// Obtain lock for x if (x == 5) { y = x * 2; // Now, nothing can change x until the lock is released. // Therefore y = 10 } // release lock for x - Question 5Mid
What is the difference between Concurrency and Parallelism?
- Software Architecture Concurrency
Reveal answerHide answer
Concurrency is when two or more tasks can start, run, and complete in overlapping time periods. It doesn't necessarily mean they'll ever both be running at the same instant. For example, multitasking on a single- core machine. Parallelism is when tasks literally run at the same time, e.g., on a multicore processor. For instance a bartender is able to look after several customers while he can only prepare one beverage at a time. So he can provide concurrency without parallelism.
- Question 8Mid
Explain Deadlock to 5 years old
- Concurrency
Reveal answerHide answer
Jack and Jill share a sparse kitchen that has only one of everything. They both want to make a sandwich at the same time. Each needs a slice of bread and each needs a knife, so they both go to get the loaf of bread and the knife from the kitchen. Jack gets the knife first, while Jill gets the loaf of bread first. Now Jack tries to find the loaf of bread and Jill tries to find the knife, but both find that what they need to finish the task is already in use. If they both decide to wait until what they need is no longer in use, they will wait for each other forever. Deadlock.
- Question 9Mid
How much work should I place inside a lock statement?
- Concurrency
Reveal answerHide answer
It is first and foremost a question of correctness. You should not care so much about efficiency trade-offs, but more about correctness.
Do as little work as possible while locking a particular object. Locks that are held for a long time are subject to contention, and contention is slow. Note that this implies that the total amount of code in a particular lock and the total amount of code in all lock statements that lock on the same object are both relevant. Have as few locks as possible, to make the likelihood of deadlocks (or livelocks) lower. If you want concurrency, use processes as your unit of concurrency. If you cannot use processes then use application domains. If you cannot use application domains, then have your threads managed by the Task Parallel Library and write your code in terms of high-level tasks (jobs) rather than low-level threads (workers). Benchmarking and being aware that there are more options than "lock everything everywhere" and "lock only the bare minimum".
- Question 10Mid
Is there any difference between a Binary Semaphore and Mutex?
- Concurrency
Reveal answerHide answer
A mutex (or Mutual Exclusion Semaphores) is a locking mechanism used to synchronize access to a resource. Only one task (can be a thread or process based on OS abstraction) can acquire the mutex. It means there will be ownership associated with mutex, and only the owner can release the lock (mutex). Semaphore (or Binary Semaphore) is signaling mechanism (“I am done, you can carry on” kind of signal). For example, if you are listening songs (assume it as one task) on your mobile and at the same time your friend called you, an interrupt will be triggered upon which an interrupt service routine (ISR) will signal the call processing task to wakeup. A binary semaphore is NOT protecting a resource from access. Semaphores are more suitable for some synchronization problems like producer-consumer. Short version: A mutex can be released only by the thread that had acquired it. A binary semaphore can be signaled by any thread (or process).
Senior questions
9 questions- Question 3Senior
What is Starvation?
- Concurrency
Reveal answerHide answer
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads or threads with more "prioroty". For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked. One more real live example may be this one. Imagine you're in a queue to purchase food at a restaurant, for which pregnant women have priority. And there's just a whole bunch of pregnant women arriving all the time. You'll soon be starving.
- Question 12Senior
What is Green Thread?
- Concurrency
Reveal answerHide answer
A Green Thread is a thread that is scheduled by a virtual machine (VM) instead of natively by the underlying operating system. Green threads emulate multithreaded environments without relying on any native OS capabilities, and they are managed in user space instead of kernel space, enabling them to work in environments that do not have native thread support. Green Thread usually used when the OS does not provide a thread API, or it doesn't work the way you need. Thus, the advantage is that you get thread-like functionality at all. The disadvantage is that green threads can't actually use multiple cores. In the context of Java specifically, there were a few early JVMs that used green
threads (IIRC the Blackdown JVM port to Linux did), but nowadays all mainstream JVMs use real threads. Theremay be some embedded JVMs that still use green threads.
- Question 13Senior
Compare Actor Model with Threading Model for concurrency
- Concurrency
Reveal answerHide answer
The actor model operates on message passing. Individual processes (actors) are allowed to send messages asynchronously to each other. What distinguishes this from what we normally think of as the threading model, is that there is (in theory at least) no shared state. And if one believes (justifiably, I think) that shared state is the root of all evil, then the actor model becomes very attractive.
- Question 14Senior
What is Starvation?
- Concurrency
Reveal answerHide answer
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads or threads with more "prioroty". For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked. One more real live example may be this one. Imagine you're in a queue to purchase food at a restaurant, for which pregnant women have priority. And there's just a whole bunch of pregnant women arriving all the time. You'll soon be starving.
- Question 15Senior
What are some advantages of Lockless Concurrency?
- Concurrency
Reveal answerHide answer
Lockless concurrency eliminates deadlocks and provides the nice advantage that readers never have to wait for other readers. This is especially useful when many threads will be reading data from a single source. Lockless programming, is a set of techniques for safely manipulating shared data without using locks. There are lockless algorithms available for passing messages, sharing lists and queues of data, and other tasks. Lockless programming is pretty complicated. e.g. All purely functional data structures are inherently lock-free, since they are immutable.
- Question 16Senior
Provide some real-live examples of Livelock
- Concurrency
Reveal answerHide answer
A real-world example of livelock occurs when two people meet in a narrow corridor, and each tries to be polite by moving aside to let the other pass, but they end up swaying from side to side without making any progress because they both repeatedly move the same way at the same time. Example of livelock will happen where a husband and wife are trying to eat soup, but only have one spoon between them. Each spouse is too polite, and will pass the spoon if the other has not yet eaten. Deadlock detection may cause livelock. If two threads detect a deadlock, and try to "step aside" for each other, without care they will end up being stuck in a loop always "stepping aside" and never managing to move forwards.
- Question 17Senior
What's the difference between Deadlock and Livelock?
- Concurrency
Reveal answerHide answer
In concurrent computing, a deadlock is a state in which each member of a group of actions, is waiting for some other member to release a lock A livelock is similar to a deadlock, except that the states of the processes involved in the livelock constantly change with regard to one another, none progressing. Livelock is a special case of resource starvation; the general definition only states that a specific process is not progressing. Livelock is a risk with some algorithms that detect and recover from deadlock. If more than one process takes action, the deadlock detection algorithm can be repeatedly triggered. This can be avoided by ensuring that only one process (chosen randomly or by priority) takes action.
- Question 18Senior
What is a Data Race?
- Concurrency
Reveal answerHide answer
A data race happens when there are two memory accesses in a program where both: target the same location are performed concurrently by two threads are not reads are not synchronization operations
- Question 19Senior
Explain what is a Race Condition to 5 years old
- Concurrency
Reveal answerHide answer
You are planning to go to a movie at 5 pm. You inquire about the availability of the tickets at 4 pm. The representative says that they are available. You relax and reach the ticket window 5 minutes before the show. I'm sure you can guess what happens: it's a full house. The problem here was in the duration between the check and the action. You inquired at 4 and acted at 5. In the meantime, someone else grabbed the tickets. That's a race condition - specifically a "check-then-act" scenario of race conditions.
Expert questions
2 questions- Question 4Expert
What happens if you have a "race condition" on the lock itself?
- Concurrency
Reveal answerHide answer
Problem
For example, two different threads, perhaps in the same application, but running on different processors, try to acquire a lock at the exact same time. What happens then? Is it impossible, or just plain unlikely?
Solution
Have a "race condition" on the lock itself is impossible. It can be implemented in different ways, e.g., via theCompare-and-swap where the hardware guarantees sequential execution. It can get a bit complicated in presence of multiple cores or even multiple sockets and needs a complicated protocol (MESI protocol) between the cores, but this is all taken care of in hardware. Compare-and-swap (CAS) is an atomic instruction used in multithreading to achieve synchronization. It compares the contents of a memory location with a given value and, only if they are the same, modifies the contents of that memory location to a new given value. This is done as a single atomic operation. The atomicity guarantees that the new value is calculated based on up-to-date information; if the value had been updated by another thread in the meantime, the write would fail.
- Question 20Expert
What is the difference between Race Condition and Data Races? Are they the same?
- Concurrency
Reveal answerHide answer
A data race occurs when 2 instructions from different threads access the same memory location, at least one of these accesses is a write and there is no synchronization that is mandating any particular order among these accesses. A race condition is a semantic error. It is a flaw that occurs in the timing or the ordering of events that leads to erroneous program behavior. Many race conditions can be caused by data races, but this is not necessary. The Race Condition and Data Races are not the same thing. They are not a subset of one another. They are also neither the necessary, nor the sufficient condition for one another.