In a single-threaded system, if a task waits for another task that is scheduled on the same thread, then we have an immediate deadlock. This is why JavaScript does not allow blocking waits, such as .wait() on promises.

In a multithreading environment, work stealing reduces the chances of deadlock or starvation, but it can still deadlock if all threads are blocked.

The issue is not limited to future.get(). Any conditional blocking (e.g. condition variables or wait) is problematic with a task system.

In a nut shell: do not call std::future.get(), std::future.wait() in standard C++, or similar constructs in other concurrency framework, when the originating task, or any subordinate task, is on the same queue, even if it is a concurrent queue (i.e. a thread pool). It is still fine to call sync blocking on the main thread or any other threads outside of the thread pool. 1

Footnotes

  1. Better Code: Concurrency - Sean Parent - YouTube