在計算機科學中，future、promise、delay 和 deferred，是在某些併發程式語言中，指稱用於同步的一種構造。由於某些計算尚未結束，故而需要一個物件來代理這個未知的結果。這種構造起源於函數語言程式設計和相關範型如邏輯程式設計，其目的是將值與其運算過程解耦，從而允許更靈活地進行計算，特別是透過將其並行化來進行。後來它在分散式計算中得到了應用，用來減少網路通訊往返的延遲。再後來 asyncawait 語法機制使其變得更有用，籍此允許以直接風格編寫非同步程式，而不再採用續體傳遞風格。 術語 在 1976 年 Daniel P Friedman 和 David Wise 提出了術語 promise ，同年 Peter Hibbard 稱之為 eventual 。1977 年和在一篇論文中介紹了一個類似的概念 future。 術語 future、promise、delay 和 deferred 通常用來稱謂同樣一種機制，在特定實現中可能只選用其中之一。在這種情況下，值與其運算過程是一起建立並且相互關聯的：future 若指稱推遲設定的一個值，設定它的函式就可稱謂為 promise；promise 若指稱推遲設定的一個值，設定它的函式就可稱謂為 resolver；promise 若指稱一個非同步函式，它的結果值所設定的就可稱謂為 future。設定一個推遲值也稱為 決定 解決（resolve）、履行 實現（fulfil）或 繫結（bind）它。 推遲值及其設定者也存在區分稱謂而同時使用的情況，二者的這種用法在不同實現中的差異將在專門章節中討論。具體來說，future 指稱一個 只讀 的變數的佔位符檢視，而 promise 指稱一個可寫的單賦值容器，使用其 成功 方法來設定這個 future 的值。尤其是在定義 future 之時，無須指定設定其值的 promise；並且可能有不同的 promise，設定同一個 future 的值；但是對於一個給定 future，僅可以進行一次設定。 歷史 future 及 或 promise 構造，首先實現於程式語言例如 和 Act 1 之中。在語言中，使用非常類似於 future 的邏輯變數進行通訊。這種語言開始於 1982 年的 Prolog with Freeze 和 IC Prolog，並且在後來的語言中變成了真正的併發原語，比如 Concurrent Prolog、、守衛霍恩子句（GHC）、、、Oz（Mozart）和。叫做 I 變數 的單賦值變數，非常類似於併發邏輯變數，它起源於資料流程程式語言的 I 結構 元件，並且包含在 Reppy 的 Concurrent ML 中。 在 1988 年 Barbara Liskov 和 Liuba Shrira，發明了 promise 流水線技術來克服傳輸延遲 Also published in ACM SIGPLAN Notices 23 7；Liskov 和 Shrira 在論文中使用了術語 promise，但是他們採用了現在少見的名稱 callstream 來提及流水線機制。在大約 1989 年、Dean Tribble 和 Rob Jellinghaus，於 Xanadu 專案中也獨立發明了此技術。 Liskov 和 Shrira 的論文中描述的設計，以及 Xanadu 中的 promise 流水線的實現，都有一個限制，即 promise 值不是頭等的：call 或 send 的引數或返回值，不能直接是 promise。在 Liskov 和 Shrira 論文中使用的程式語言 Argus，直至大約 1988 年停止開發，似乎都未曾在任何公開發布中實現 promise 和 callstream 。Xanadu 實現的 promise 流水線，僅在 1999 年 Udanax Gold 的原始碼釋出時才公開發布 ，並且在任何已釋出的文件中都沒有解釋過。 一些早期的演員語言，包括 Act 系列，支援並行訊息傳遞和流水線式訊息處理，但不支援 promise 流水線。和 E 語言的後續實現，支援完全頭等的 promise 和 resolver，還有 promise 流水線。 2000 年之後，由於的請求 響應模型，在使用者介面和 Web 開發中的應用，future 和 promise 重新引起了人們的興趣。現在一些主流語言對 future 和 promise 有了語言支援，最著名的是 2004 年發行的 Java 5 中的 FutureTask，以及 2012 年發行的NET 框架 45 中的 asyncawait 結構 ，它在很大程度上受到可追溯到 2007 年的 F 非同步程式設計模型 的啟發。asyncawait 隨後被其他語言採用，特別是 2014 年的 Dart 19、2014 年發行的 Hack（HHVM）、2015 年的 Python 35、ECMAScript 2017、2019 年的 Rust 139 和 C20 等。 實現列表 程式語言支援 下面列出支援 future、promise 和併發邏輯變數、資料流程變數或 I 變數的語言，包括直接在語言中支援還有在標準庫中支援： ABCLf ，支援 future ，包含頭等的 resolver 和只讀 promise C，從 C11 開始有 stdfuture 和 stdpromise Concurrent ML，僅限 I 變數和 M 變數 Dart，使用 FutureCompleter 類以及關鍵字 asyncawait Elm，透過 Task 模組 Glasgow Haskell，僅限同步可變變數 MVars ，僅限 I 結構和 M 結構 Io Java，透過 Future 或 CompletableFuture JavaScript，始於 ECMAScript 2015 提供 Promise 物件，並且自從 ECMAScript 2017 可透過關鍵字 asyncawait 來使用 Lucid，僅限作為串流的變數 一些 Lisp Clojure Racket NET，自NET 框架 40 起透過 TPL C，自NET 框架 45 起，透過關鍵字 asyncawait Visual Basic，自從版本 11，透過關鍵字 AsyncAwait Kotlin，但是 kotlinnativeconcurrentFuture 通常只在書寫本機執行程式碼時使用 Nim，使用 asyncawait 語法 Oz 版本 3 Python，自從 2011 年版本 32 提供 concurrentfutures 模組，這是由 PEP 3148 所提議，而 2015 年版本 35 增加了基於低層 future 的 asyncio 模組，它採用高層 asyncawait 語法 R，延遲計算的 promise，仍然是單執行緒 Raku Rust，通常經由await 完成 Scala，透過 scalaconcurrent 包 scalaconcurrent 包 Scheme，僅延遲求值 Squeak Smalltalk 還支援 promise 流水線的語言包括： E 非標準庫的實現 對於 Common Lisp： Blackbird Eager Future2 lparallel Common Lisp 的並行程式設計庫 PCall 對於 C： Boost library Qt Seastar Folly ，ActiveResult 對於 C 和其他NET 語言： 庫 對於 Groovy： GPars 對於 JavaScript： PromisesA 標準網站，有此標準的實現的列表 Cujojs 的 whenjs，提供的 promise 符合 PromisesA 11 標準 Dojo Toolkit，提供 promise 和 Twisted 風格 Deferred ，受 Twisted 的 Deferred 的啟發 jQuery 的 Deferred 物件，基於了 CommonJS PromisesA 規定 CommonJS PromisesA AngularJS Q，符合 PromisesA 11 標準 RSVPjs，符合 PromisesA 11 標準 Bluebird 的 promise 包 promise，符合 PromisesA 標準 對於 Java： JDeferred，提供了與 JQueryDeferred 物件類似的 deferredpromise API 和行為 ParSeq，提供 taskpromise API，由 LinkedIn 維護，適用於非同步流水線和分支 對於 ObjectiveC： MAFuture、RXPromise、ObjCCollapsingFutures、PromiseKit、objcpromise、OAPromise 對於 OCaml： Lazy 模組實現了懶惰的顯式 future 對於 Perl： Future、Promises、Reflex 對於 PHP： ReactPromise 對於 Python： promise Twisted 的 Deferred 對於 R： future，實現可擴充套件的 future API 與懶惰和及早同步和（多核或分散式）非同步 future 對於 Ruby： Promise gem libuv gem，實現 promise Celluloid gem，實現 future futureresource 對於 Rust： futuresrs 對於 Scala： Twitter 的 util 庫 對於 Swift： 非同步框架，實現 C 風格的 async 非阻塞 await FutureKit，Apple 的 GCD（Grand Central Dispatch）實現版本 FutureLib，純 Swift 2 庫實現的 Scala 風格的 future 和 promise 與 TPL 風格的取消 Deferred，純 Swift 庫，受到 OCaml 的 Deferred 啟發 BrightFutures 對於 Tcl： tclpromise 自行實現 future 可以用協程或生成器實現，從而具有相同的求值策略（例如協同多工或延遲求值）。 future 還可以很容易地用通道實現：future 是一個單元素的通道，而 promise 是一個傳送到通道，實現 future 的過程。這允許 future 在支援通道（如 CSP 和 Go）的併發程式語言中實現。由此產生的 future 是顯式的，因為它們必須透過從通道讀取而不是僅僅透過求值來獲取。 程式語言典型示例 Python Python 的 concurrentfutures 模組，提供了可呼叫物件的高層介面。非同步執行可以使用執行緒池執行器 ThreadPoolExecutor，透過多個執行緒來進行；或使用程序執行器 ProcessPoolExecutor，透過分立的多個程序來進行。concurrentfuturesFuture 類封裝了可呼叫物件的非同步執行，其例項由執行器抽象類 Executor 的這兩個子類的 submit 方法建立。 在下面的例子中，定義了 load_url ，用來檢索一個 URL 所指定的單一網頁並報告其內容。使用 with 語句指定採用執行緒池執行器，這確保了執行緒由它及時清理。用這個執行器的 submit 方法啟動所有的裝載操作任務，並使用字典推導式為其建立的每個 future 標記上對應的 URL。採用模組函式 as_completed ，在指定的 Future 類的諸例項 已齊全（completed）之時，建立在其上的迭代器。 import concurrentfutures import urllibrequest URLS httpswwwpythonorg httpspypiorgsearch httpsnosuchurl def load_url url timeout with urllibrequesturlopen url timeouttimeout as conn return connread with concurrentfuturesThreadPoolExecutor as executor future_to_url executorsubmit load_url url 60 url for url in URLS for future in concurrentfuturesas_completed future_to_url url future_to_url future try data futureresult except Exception as exc print furlr generated an exception excs else print furlr page is len datad bytes 在 CPython 中，由於全域性直譯器鎖（GIL），保證一時只有一個執行緒可以執行 Python 位元組碼；一些擴充套件模組被設計為在進行計算密集任務時釋放 GIL，還有在進行 IO 時總是釋放 GIL。執行緒池執行器的 max_workers 引數的預設值是 min 32 oscpu_count 4，這個預設值為任務保留至少 5 個 worker 執行緒，為釋放 GIL 的 CPU 踴躍任務利用最多 32 個 CPU 邏輯核心。想要更好利用多核心機器的計算資源，可以使用程序池執行器或多程序模組 multiprocessing。對於同時執行多個任務，仍然適合採用執行緒池執行器或執行緒模組 threading。 Python 的非同步 IO 模組 asyncio，是採用 asyncawait 語法編寫併發程式碼的庫。asyncio 模組基於低層事件迴圈，提供的高層 API 包括了：併發執行 Python 協程並擁有在其執行上的完全控制，進行網路 IO 和 IPC，控制子程序，透過佇列分佈和同步併發程式碼。asyncio 模組的同步原語，在設計上類似於 threading 模組的同步原語，但與之相比有兩個重要差異：asyncio 模組的同步原語不是執行緒安全的，故而不能用於 OS 執行緒同步；這些同步原語的方法不接受實際引數。 asyncio 模組提供的低層 API 中有 asyncioFuture 物件，用來橋接低層基於回撥的程式碼和高層採用 asyncawait 語法的程式碼，它在設計上模仿了 concurrentfuturesFuture 物件。這兩個模組的 Future 物件的 set_result 方法標記這個 Future 物件為 已完畢（done）並設定它的結果，而 set_exception 方法標記這個 Future 物件為已完畢並設定一個例外；done 方法在這個 Future 物件已完畢時返回 True；result 方法返回這個 Future 物件所設定的結果，或者引發其所設定的例外。 二者的關鍵差異包括了：asyncioFuture 是可期待（awaitable）物件，而 concurrentfuturesFuture 物件不可以被期待（awaited）。asyncioFutureresult 不接受超時實際引數，如果此刻這個 Future 物件的結果仍不可獲得，它引發一個 InvalidStateError 例外；而 concurrentfuturesFutureresult ，可接受（timeout）實際引數，如果此刻結果仍未 完全（completed），它等待指定時間後若仍未完全則引發 TimeoutError 例外，如果超時未指定或指定為 None，則對等待時間沒有限制。 JavaScript 在 JavaScript 中，Promise 物件表示一個運算的最終完成或失敗，及其結果值或失敗理由。Promise 物件是對一個值的代理（proxy），這個值在建立這個 promise 之時不必需已知。promise 允許為非同步行動的最終成功值或失敗理由關聯上處理器，這使得非同步方法像同步方法那樣返回值：並非立即返回最終值，非同步方法返回一個 promise 來在將來的某一點上提供這個值。 在 JavaScript 生態系統中，Promise 物件在成為語言本身的一部份之前很久就有了多種實現。儘管各有不同的內部表示，至少幾乎所有類似 Promise 的物件都實現了 可接續（thenable）介面。可接續物件實現了then 方法，Promise 物件就是可接續的。 一個 promise 被稱為已落實（settled），如果它要麼已履行（fulfilled）要麼已拒絕（rejected），而不再待定（pending）。Promise 例項的then 方法，接受一到二個實際引數，它們是作為處理器非同步執行的回撥函式，分別針對了這個 promise 的已履行和已拒絕情況；此方法返回一個新的 promise，它決定（resolve）出其所呼叫處理器的返回值，或者在原來這個 promise 未被處理的情況下，仍決定出其已落實的值。Promise 例項的catch 方法，實際上就是置空針對已履行情況的回撥函式，而只有針對已拒絕情況的回撥函式的then 方法。 Promise 構造子建立 Promise 物件，它主要用於包裝仍基於回撥的 API 所提供的運算，要注意它只能透過 new 運算元來構造：new Promise executor。Promise 構造子的實際引數叫做 執行器（executor），它是由這個構造子同步執行的一個函式，它有可自行指定名字的兩個函式形式引數，比如指定為 resolveFunc 和 rejectFunc，這兩個函式接受任何型別的單一實際引數。 Promise 構造子返回的 Promise 物件，在要麼 resolveFunc 函式要麼 rejectFunc 函式被呼叫之時，它就成為 已決定（resolved）的。要注意如果在呼叫這兩個函式之一的時候，將另一個 Promise 物件作為實際引數傳遞給它，則這個 Promise 物件可以稱為已決定但仍未落實。在執行器中有任何錯誤丟擲，都會導致這個 promise 成為已拒絕狀態，而返回值會被忽略。 Promise 類提供四個靜態方法來實施非同步併發，其中的 PromiseallSettled 方法，接受有多個 promise 的可迭代物件作為輸入，當所有輸入的 promise 都已落實之時，返回一個單一的已履行的 Promise 物件，它決定出描述每個輸入 promise 的結果的一個物件陣列；其中每個物件都有 status 屬性，它是字串 fulfilled 或者 rejected；還有在 status 為 fulfilled 時出現的屬性 value，或者在 status 為 rejected 時出現的屬性 reason。 在下面例子中，全域性 fetch 方法，啟動從網路上取回一個資源的過程，並返回一旦響應可獲得就履行的一個 promise；這個 promise 決定出表示對這個請求響應的一個 Response 物件，它只在遇到網路錯誤之時拒絕。Responsetext 方法返回一個 promise，它決定出這個響應的主體的一個文字表示。 const urls httpsdevelopermozillaorg httpsjavascriptinfopromiseapi httpsnosuchurl const fetchPromises urlsmap url fetch url PromiseallSettled fetchPromises then results resultsforEach result num if resultstatus fulfilled if resultvalueok resultvaluetext then data consolelog urls num datalength bytes catch err consoleerror err else consolelog urls num resultvaluestatus else if resultstatus rejected consoleerror urls num resultreason JavaScript 是天然的單執行緒的，所以在給定時刻只有一個在，但控制可以在不同的 promise 之間轉移，使得多個 promise 表現為併發執行。在 JavaScript 中並行執行只能透過分立的 worker 後臺執行緒來完成。 同基於 promise 的程式碼合作的一種更簡單的方式，是使用 asyncawait 關鍵字。在函式開始處增加 async，使其成為非同步函式，函式總是返回一個 promise。在非同步函式中，可以在對返回一個 promise 的函式的呼叫之前，使用 await 關鍵字；這使得程式碼在這一點上等待直到這個 promise 已落實下來，然後在這一點上 promise 的已履行的值被當作返回值，而已拒絕的理由被作為例外丟擲。可以使用 trycatch 塊進行例外處理，就如同這個程式碼是同步的一樣。 只讀檢視 在某些程式語言（如 Oz、E 和）中，可以獲得推遲值的 只讀檢視，允許在解決（resolve）出這個值之後透過它來讀取，但不允許透過它來解決這個值： 在 Oz 語言中， 運算子用於獲得只讀檢視。 在 E 語言和 AmbientTalk 中，推遲值由一對稱為 promiseresolver 對 的值表示。promise 表示只讀檢視，需要 resolver 來設定推遲值。 在 C11 中，stdfuture 提供了一個只讀檢視。該值透過使用 stdpromise 直接設定，或使用 stdpackaged_task 或 stdasync 設定為函式呼叫的結果。 在 Dojo Toolkit 的 15 版本的 Deferred API 中，僅限 consumer 的 promise 物件 表示只讀檢視。 在中，future 提供 只讀檢視，而 promise 包含 future 和解決 future 的能力。 在NET 40 中，SystemThreadingTasksTaskT 表示只讀檢視。解決值可以透過 SystemThreadingTasksTaskCompletionSourceT 來完成。 對只讀檢視的支援符合最小特權原則，因為它使得設定值的能力僅限於需要設定該值的主體。在同樣支援流水線的系統中，非同步訊息（具有結果）的傳送方接收結果的只讀 promise，訊息的目標接收 resolver。 有關結構 future 是事件同步原語的特例，它只能完成一次。通常，事件可以重置為初始的空狀態，因此可以根據需要多次完成。500 lines or less A Web Crawler With asyncio Coroutines by A Jesse Jiryu Davis and Guido van Rossum says implementation uses an asyncioEvent in place of the Future shown here The difference is an Event can be reset whereas a Future cannot transition from resolved back to pending Ivar 是具有下面定義的阻塞語義的 future。它起源於 Id 語言中包含 Ivar 的 Istructure 資料結構。可以使用不同值多次設定的有關同步構造稱為 Mvar。Mvar 支援 take（採取）或 put（放置）當前值的原子性操作，這裡採取這個值還將 Mvar 設定回其初始的 空 狀態。 併發邏輯變數 與 future 類似，但是透過合一更新，與邏輯程式設計中的 邏輯變數 相同。因此，它可以多次繫結到可合一的值，但不能設定回到空或未解決狀態。Oz 的資料流變數充當併發邏輯變數，並且還具有上面提到的阻塞語義。 併發約束變數 是併發邏輯變數的一般化，以支援約束邏輯程式設計：約束可以多次 縮小，表示可能值的較小集合。通常，有一種方法可以指定每當約束進一步縮小時應該執行的；這是支援 約束傳播 所必需的。 隱式與顯式 future 對 future 的使用可以是 隱式 的，任何對 future 的使用都會自動獲得它的值，它就像是普通的引用一樣；也可以是 顯式 的，使用者必須呼叫函式來獲取值，例如 Java 中的 Future 或 CompletableFuture 的 get 方法。獲得一個顯式的 future 的值可以稱為 刺激（stinging）或 強迫（forcing）。顯式 future 可以作為庫來實現，而隱式 future 則通常作為語言的一部分來實現。 最初的 Baker 和 Hewitt 論文描述了隱式 future，它們在演員模型和純面向物件程式語言（如 Smalltalk）中自然得到支援。Friedman 和 Wise 的論文只描述了顯式的 future，可能反映了在老舊硬體上有效實施隱式 future 的困難。難點在於老舊硬體不能處理原始資料型別（如整數）的 future。例如，add 指令不會處理 3 future factorial 100000 。在純演員模型或面嚮物件語言中，這個問題可以透過向 future factorial 100000 傳送訊息 3 來解決，它要求 future 自己加 3 並返回結果。請注意，無論 factorial 100000 何時完成計算，訊息傳遞方法都可以工作，而且不需要任何 刺激 或 強迫。 阻塞與非阻塞語義 如果 future 的值是非同步訪問的，例如透過向它傳送訊息，或者透過使用類似於 E 語言中的 when 的構造顯式地等待它，那麼在訊息可以被接收或等待完成之前，推遲直到 future 得到解決（resolve）是沒有任何困難的。這是在純非同步系統（如純演員語言）中唯一需要考慮的情況。 然而，在某些系統中，還可能嘗試 立即 或 同步 訪問 future 的值。這樣的話就需要做出一個設計選擇： 訪問可能會阻塞當前執行緒或程序，直到 future 得到解決（可以具有超時）。這是 Oz 語言中 資料流變數 的語義。 嘗試的同步訪問總是會引發訊號指示錯誤，例如丟擲異常。這是 E 語言中遠端 promise 的語義。 潛在的，如果 future 已經解決，則訪問可能成功，但如果未解決，則發出訊號指示錯誤。這樣做的缺點是引入了不確定性和潛在的競爭條件，這似乎是一種不常見的設計選擇。 作為第一種可能性的示例，在 C11 中 ，需要 future 值的執行緒可以透過呼叫 wait 或 get 成員函式來阻塞，直到它可獲得為止。還可以使用 wait_for 或 wait_until 成員函式指定等待超時，以避免無限期阻塞。如果 future 對 stdasync 的呼叫，那麼阻塞等待（沒有超時）可能導致函式的同步呼叫以計算等待執行緒上的結果。 promise 流水線 在分散式系統中使用推遲值可以顯著地減少傳輸延遲。例如，指稱推遲值的 promise，成就了 promise 流水線，就像在 E 語言和語言中實現的那樣，它在 Argus 語言中稱為 callstream。 考慮一個涉及常規遠端過程呼叫的表示式，例如： t3 xa c yb 可以展開為 t1 xa t2 yb t3 t1c t2 每個語句需要傳送一條訊息，並在下一個語句可以繼續之前收到一個答覆。例如，假設 x、y、t1 和 t2 都位於同一臺遠端機器上。在這種情況下，在開始執行第三條語句之前，必須對該機器進行兩次完整的網路往返。然後，第三條語句將引起另一個到同一個遠端機器的往返。 上面的表示式可以使用 E 語言的語法寫為： t3 x a c y b 其中 x a 表示將訊息 a 非同步傳送給 x。它可以展開為： t1 x a t2 y b t3 t1 c t2 所有三個變數都會立即為其結果分配 promise，執行過程將繼續進行到後面的語句。之後嘗試解決 t3 的值可能會導致傳輸延遲；但是，流水線操作可以減少所需的往返次數。如果與前面的示例一樣，x、y、t1 和 t2 都位於相同的遠端機器上，則流水線實現可以用一次往返來計算 t3，不必用三次。由於所有三條訊息都指向同一遠端計算機上的物件，因此只需要傳送一個請求，只需要接收一個包含結果的響應。另請注意，即使 t1 和 t2 位於不同機器上，或者位於與 x 或 y 不同的機器上，傳送 t1 c t2 也不會阻塞。 promise 流水線應與並行非同步訊息傳遞區分開來。在支援並行訊息傳遞但不支援流水線操作的系統中，上面示例中的訊息傳送 x a 和 y b 可以並行進行，但傳送 t1 c t2 將不得不等到 t1 和 t2 都被接收，即使 x、y、t1 和 t2 在同一個遠端機器上。在涉及許多訊息的更復雜情況下，流水線的相對傳輸延遲優勢變得更大。 promise 流水線操作也不應與演員系統中的流水線式訊息處理相混淆，在這種系統中，演員可以在完成當前訊息的處理之前，指定並開始執行下一個訊息的行為。 有特定執行緒的 future 某些語言比如，定義的 future 可以關聯著計算這個 future 值的特定執行緒。這種計算可以透過 spawn exp，在建立 future 時及早地開始；或者透過 lazy exp，在首次需要其值時懶惰地開始。在延遲計算的意義上，懶惰的 future 類似於 thunk 。 Alice ML 還支援可由任何執行緒解決的 future，並稱謂它們為 promised future。這裡的 promise 是給 future 的顯式把柄（handle），它透過多型庫函式 Promisepromise 來建立，所有 promise 都關聯的一個 future，建立一個新 promise 也就建立了一個新鮮的 future；這個 future 透過 Promisefuture 來提取，並且透過顯式的應用 Promisefulfill 於對應的 promise 來消除，即在全域性中將這個 future 替代為一個值。Alice ML 不支援 promise 流水線，轉而對於 future，包括關聯著 promise 的 future，流水線是自然而然地發生的。 在沒有特定執行緒的 future（如 Alice ML 所提供的）中，透過在建立這個 future 的同時建立一個計算這個值的執行緒，可以直接實現及早求值的有特定執行緒的 future。在這種情況下，最好將只讀檢視返回給客戶，以便僅讓新建立的執行緒能夠解決這個 future。 要在沒有特定執行緒的 future 中，實現隱式惰性的有特定執行緒的 future，需要一種機制來確定何時首次需要 future 的值（例如，Oz 中的 WaitNeeded 構造 ）。 如果所有值都是物件，那麼有實現透明轉發物件的能力就足夠了，因為傳送給轉發器的首條訊息表明需要 future 的值。 假定系統支援訊息傳遞，在有特定執行緒的 future 中，透過讓解決執行緒向 future 自己的執行緒傳送訊息，可以實現沒有特定執行緒的 future。然而這可能被視為不必要的複雜性。在基於執行緒的程式語言中，最具表現力的方法似乎是提供一種混合：沒有特定執行緒的 future、只讀檢視、以及要麼有 WaitNeeded 構造要麼支援透明轉發。 傳 future 呼叫 就求值策略而言，傳 future 呼叫 是非確定性的：future 的值將在建立 future 和使用其值之間的某個時間進行求值，但確切的時間不確定的，一次執行和另一次執行的求值時間會不一樣。計算可以在建立 future 時開始（及早求值），或者僅在實際需要值時開始（懶惰求值），並且可以在中途暫停，或在一次執行中執行。一旦 future 被賦值，它就不會在訪問 future 的時候重新計算；這就像傳需求呼叫時使用的記憶化。 懶惰 future 是確定性的具有惰性求值語義的 future：future 值的計算在首次需要時開始，與傳需要呼叫一樣。懶惰 future 使用在求值策略預設不是懶惰求值的語言中。例如，在 C11 中，可以透過將 stdlaunchdeferred 啟動策略傳遞給 stdasync 以及計算值的函式來建立這種惰性 future。 演員模型中的 future 語義 在演員模型中，形式為 future Expression 的表示式，以它對具有環境 E 和客戶 C 的 Eval 訊息的響應方式來定義：future 表示式透過向客戶 C 傳送新建立的演員 F（計算 Expression 的響應的代理）作為返回值來響應 Eval 訊息，與之併發的向 Expression 傳送具有環境 E 和客戶 F 的 Eval 訊息。F 的預設行為如下： 當 F 收到請求 R 時，它會檢查是否已經收到來自求值 Expression 的響應（可以是返回值或丟擲異常），處理過程如下所示： 如果它已經有了響應 V，那麼 如果 V 是返回值，那麼向它傳送請求 R。 如果 V 是一個異常，那麼就把這個異常拋給請求 R 的客戶。 如果它還沒有響應，那麼將 R 儲存在 F 內的請求佇列中。 當 F 接收到來自求值 Expression 的響應 V 時，那麼將 V 儲存在 F 中，並且 如果 V 是返回值，那麼將所有排隊的請求傳送到 V。 如果 V 是一個異常，那麼就會把這個異常丟擲給每個排隊請求的客戶。 但是，一些 future 可以透過特殊方式處理請求以提供更大的並行性。例如，表示式 1 future factorial n 可以建立一個新的 future，其行為類似於數字 1factorial n 。這個技巧並不總是有效。例如，以下條件表示式： if mfuture factorial n then print bigger else print smaller 會掛起，直到 factorial n 這個 future 已回應詢問 m 是否大於其自身的請求。 參見 監視器 程式同步化 詛咒金字塔 程式設計 引用 外部連結 Concurrency patterns presentation given at scaleconf Future Value and Promise Pipelining at the Portland Pattern Repository Easy Threading with Futures in Python Category 程序間通訊 Category 併發計算