Concepts / Understanding Futures and Promises

Understanding Futures and Promises

A future and a promise are related objects that together move a value from one task to another.

  • Programming

A Value That Must Change Hands

Imagine two tasks running side by side. One of them computes something the other one needs. The first task has to get its result to the second task. This is an everyday problem in concurrent programming, and it is the situation that futures and promises were designed to solve.

What do you think happens?

Two tasks need to pass one value between them. Before reading on, which object do you think the producing task places its value into?

  • A future

  • A promise

  • The reading task directly

  • A shared variable guarded by a lock

Reveal answer
Answer:

A promise

The producing task places its value into a promise. The implementation then makes that value appear in the corresponding future, which is the object the reading side looks at. Notice that the producer never reaches into the future itself.

Why Tasks Need a Handoff

A value computed in one task is useful only when another task can receive it. Without a dedicated handoff, the programmer must coordinate every transfer by hand, deciding when the value is ready, where it is stored, and how the other task finds it. That coordination is easy to get wrong.

Futures and promises provide a mechanism for this exact job: moving a value from one task to another. What makes them useful is that the mechanism lets the value travel between tasks while the system takes care of the transfer itself. The programmer names the two sides of the handoff rather than scripting each step of it.

The Promise and the Future as a Linked Pair

Definition

A future and a promise are related objects that together move a value from one task to another. The promise is the object the producing task writes to. The future is the object the reading side reads from. The two are connected, so a value placed into the promise appears in the corresponding future.

Promiseproducing task writes hereFuturereading side reads herecorresponding pair
Which object does the producing task write to, which object does the reading side read from, and how are the two connected?

The two objects have distinct roles. The promise is the write-side object, and the producing task's job ends there once the value is placed in it. The future is the read-side object, and it is where the value can be picked up. Keeping these two roles separate in your head is the key to reasoning about everything that follows.

Tracing a Value from Producer to Reader

The basic idea can be stated in three moves. First, a task that wants to pass a value to another task places that value into a promise. Second, the implementation makes the value show up in the corresponding future. Third, the value can be read from that future. The source names the launcher of the task as the usual reader.

Producing taskcomputes the valuePromisevalue is placed hereFuturevalue appears hereReaderlauncher reads the valueplaces valueimplementation deliversvalue is read
Where does the value start, which objects does it pass through, and where does it finally arrive?

Notice what the producing task does not do. It never has to reach into the future. Its responsibility stops at the promise. The middle step deserves attention. The source says the implementation makes the value appear in the future, but it does not describe how that happens. What you need to hold onto is the outcome: the value leaves the producing task through the promise and arrives at the future, which is the object the reading side looks at.

Worked example

Following One Total Across Two Tasks

Task A computes a total of 42. Task B needs that total. Trace the path of the value 42 from Task A to Task B using a promise and a future.

  1. 1
    Identify the producer

    Task A computes 42, so Task A is the producing task. It is the only side that places a value into the promise.

  2. 2
    Write to the promise

    Task A places 42 into the promise. Its job for this value ends here.

  3. 3
    Implementation delivers

    The implementation makes 42 appear in the corresponding future. The programmer does not write this step.

  4. 4
    Read from the future

    Task B's launcher reads 42 from the future, since the launcher is the usual reader.

Result

The value 42 leaves Task A through the promise, arrives in the future, and is read by the reading side. Task A never touched the future, and Task B never touched the promise.

Why No Lock Appears in Your Code

The defining feature of futures and promises is that they move a value between two tasks without explicit use of a lock. In a setting where you might otherwise coordinate access to shared data by acquiring and releasing a lock yourself, this mechanism removes that step from your code. You do not write the coordination; the system provides it.

Mistakes in Choosing Write and Read Targets

Most errors with futures and promises come from mixing up which object belongs to which side. The mistakes below are common ways a learner might route a value to the wrong place.

  • Common mistake

    Thinking the producing task writes to the future

    What it looks like

    Task A tries to place 42 directly into the future and skips the promise.

    Why it fails

    The producing task places its value into the promise. The future is where the value appears after the implementation moves it.

    Do this instead

    Route the producer's value into the promise, and let the value arrive in the future.

  • Common mistake

    Thinking the reading side reads from the promise

    What it looks like

    Task B looks in the promise to find the total of 42.

    Why it fails

    The promise is the write-side object. The reading side looks at the future, which is where the value appears.

    Do this instead

    Read the value from the future.

  • Common mistake

    Expecting the producer to read back the value it wrote

    What it looks like

    Task A places 42 into the promise and then reads from the future to confirm it.

    Why it fails

    The producer's job ends at the promise. The reading side is the party that picks the value up from the future.

    Do this instead

    Let the reading side own the read, and keep the producer's responsibility limited to writing.

  • Common mistake

    Confusing the two objects because they are linked, so treating them as one interchangeable thing

QuestionCorrect answerCommon wrong answer
Which object does the producing task write to?The promiseThe future
Which object does the reading side read from?The futureThe promise
Where does the value appear after the handoff?In the futureIn the promise
Does the producer need to read the value back?No, its job ends at the promiseYes, to confirm the transfer

Write-side and read-side roles for a value moving between two tasks

Practice Tracing the Path

EASY

A producing task computes the value 7. Name the object the producer writes to, the object where the value appears, and the party that reads it.

Hints
  • Start with the producer. Which object does it place its value into?
  • The implementation makes the value appear in the corresponding future. Which object is that?
  • The launcher of the task is the usual reader. Which object does the reader look at?
MEDIUM

Two tasks share a value. A teammate says, the reader should write its result into the promise so the producer can pick it up from the future. Explain what is wrong with this plan, using the roles of the promise and the future.

Hints
  • Reread which side of the pair is the write side and which is the read side.
  • Ask which object the producer is supposed to write to, and which object the reader is supposed to read from.

Key Takeaways

  • Tasks need a way to hand values to one another, and futures and promises are a mechanism built for that handoff.
  • A promise is the object the producing task writes to, and the corresponding future is the object the reading side reads from.
  • A value travels from the producing task into the promise, appears in the future, and is read from the future by the reader.
  • The transfer happens without explicit use of a lock, because the system implements it, but the roles of the write side and the read side still matter.

More concepts starting with U