Atomics.pause()

基準線 2025
新推出

自 ⁨2025 年 4 月⁩起,此功能適用於最新裝置和瀏覽器版本。此功能可能不適用於較舊的裝置或瀏覽器。

Atomics.pause() 靜態方法提供了一種微等待原語,它提示 CPU 呼叫者正在忙等待(spinning)以訪問共享資源。這允許系統減少分配給核心(如功耗)或執行緒的資源,而無需讓出當前執行緒。

除了計時外,pause() 沒有其他可觀察的行為。具體行為取決於 CPU 架構和作業系統。例如,在 Intel x86 上,它可能是一個 pause 指令,根據 Intel 的最佳化手冊。在某些平臺上,它可能是一個空操作(no-op)。

語法

js
Atomics.pause()
Atomics.pause(durationHint)

引數

durationHint 可選

一個實現可以用來確定等待時間的整數。對於值 n + 1,實現等待的時間至少與給定值 n 的時間一樣長。具體數字沒有實際意義。在納秒到幾十納秒的量級上,可能存在內部最大暫停時間的上限。這可以用來透過增加傳遞的 durationHint 來實現 退避策略。不能保證實現一定會利用此提示。

返回值

無(undefined)。

異常

TypeError

如果 durationHint 不是整數或 undefined,則丟擲錯誤。

示例

使用 Atomics.pause()

呼叫 Atomics.wait()Atomics.waitAsync() 來等待訪問共享記憶體會導致執行緒被排程出核心,並在等待結束後重新排程回核心。在高爭用時期,這非常高效,因為訪問共享記憶體可能需要一些時間。當爭用較低時,通常更有效的方法是在不讓出執行緒的情況下輪詢鎖:這種方法稱為 忙等待自旋鎖pause() 方法透過向 CPU 提供執行緒正在做什麼的提示,從而降低其對資源的需求,使您能夠更有效地自旋鎖等待。

為了兼顧這兩種情況,一種常見的方法是首先嚐試自旋鎖,希望能快速獲取鎖(爭用低),然後在一段時間後如果仍未獲得鎖,則進行等待。如果我們已經透過自旋鎖獲取了鎖,那麼 wait() 呼叫將是一個空操作。

下面的示例顯示瞭如何將這種方法與 Atomics.pause()Atomics.wait() 結合使用。

警告:不建議在主執行緒上使用自旋鎖,因為它會凍結整個頁面。總的來說,除非經過非常仔細的設計,否則自旋鎖的效能可能並不比常規等待更好。

js
// Imagine another thread also has access to this shared memory
const sab = new SharedArrayBuffer(1024);
const i32 = new Int32Array(sab);

// Fast path: spin the CPU for a short while
let spin = 0;
do {
  if (Atomics.compareExchange(i32, 0, 0, 1) === 0) {
    break;
  }
  Atomics.pause();
  spin++;
} while (spin < 10);

// Slow path: wait for the lock
// This can only be called in a worker thread,
// because the main thread cannot be blocked
Atomics.wait(i32, 0, 1);

退避策略

durationHint 引數可用於實現退避策略。例如,執行緒可以從一個小的提示開始,並在每次迭代中指數級增加提示。這比多次呼叫 pause() 要好,因為在未 JIT 編譯的程式碼中,函式呼叫本身就有很高的開銷。

注意:實現可能根本不使用 durationHint,而是始終等待一個固定的時間。

js
// Exponential backoff
for (let hint = 1; hint < 1000; hint *= 2) {
  Atomics.pause(hint);
}

// Linear backoff
for (let hint = 1; hint < 100; hint++) {
  Atomics.pause(hint);
}

規範

規範
Atomics.pause
# Atomics.pause

瀏覽器相容性

另見