Does standard C11 guarantee that stdasyncstdlaunchasync, func launches func in separate thread?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
std::async is one of the most useful concurrency tools added in C plus plus 11. The short answer is that std::async(std::launch::async, func) does guarantee asynchronous execution, but developers often misread what is guaranteed and what is implementation detail. The key is to separate the required behavior from assumptions about operating system threads.
What std::launch::async Actually Guarantees
When you pass std::launch::async, the callable is required to run in a separate thread of execution from the caller. That means the work cannot be deferred until get or wait is called, which is what std::launch::deferred allows. The function starts asynchronously, and the returned std::future represents that running task.
A practical way to observe this is to compare thread ids and timing.
On normal implementations you will see a different thread id. The standard guarantee is about separate execution, not the exact runtime strategy.
async Versus deferred
Many bugs come from forgetting that default launch policy is allowed to choose either async or deferred. If you omit a policy, the implementation may delay execution until get or wait, which can make code appear single threaded under load tests.
In this example the deferred task does not begin until f1.get. That behavior is correct and often surprising.
Lifecycle Rules That Matter in Production
A std::future from std::async is not just a value holder. It also participates in synchronization. If the task is running asynchronously and the last future referring to the shared state is destroyed before completion, destruction can block until the task finishes. This prevents detached background tasks from silently escaping lifetime management.
That blocking behavior is useful for safety, but it can also create latency spikes if futures are destroyed on critical threads.
Depending on implementation, this can pause at scope exit because the temporary future is destroyed.
Choosing the Right Pattern
Use std::launch::async when you need concurrent progress and explicit overlap with caller work. If you only need lazy evaluation, use deferred intentionally. If you need advanced pooling, cancellation, or cooperative scheduling, consider higher-level executors or task systems in your stack, since plain std::async gives limited control over queueing and thread reuse.
For reliable behavior in performance sensitive code, always specify launch policy explicitly and treat the future as part of your synchronization design.
Common Pitfalls
- Assuming default policy always means a new thread. Fix by passing
std::launch::asyncexplicitly when concurrency is required. - Treating
std::asyncas detached fire and forget. Fix by storing the returnedfutureand managing its lifetime intentionally. - Calling
gettoo early and losing parallelism. Fix by starting all tasks first, then collecting results later. - Ignoring exception flow from worker code. Fix by handling exceptions around
future.get, since worker exceptions are rethrown there. - Expecting fine grained scheduler control. Fix by using a custom executor framework when you need priority, throttling, or affinity.
Summary
std::launch::asyncguarantees asynchronous execution on a separate thread of execution.- Default launch policy may choose deferred, so behavior can vary if policy is omitted.
std::futurelifetime affects blocking and correctness.- Explicit policy plus explicit result collection gives predictable concurrency.
- Treat
std::asyncas a high level convenience, not a full scheduler.
Related reading
- Does Task.ContinueWith capture the calling thread context for continuation?
- Does TensorFlow by default use all available GPUs in the machine?
- Does TensorFlow job use multiple cores by default?
- Does TensorFlow view all CPUs of one machine as ONE device?
- Does the C volatile keyword introduce a memory fence?
- Does the Java Memory Model JSR-133 imply that entering a monitor flushes the CPU data caches?
- Does the SQL Server JDBC driver support asynchronous operations?
- Does the use of async/await create a new thread?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.