0Pricing
WebAssembly (WASM) for High Performance Apps · บทเรียน

SharedArrayBuffer และอะตอมิกสำหรับ WASM

ใช้ SharedArrayBuffer และการดำเนินการแบบอะตอมิกเพื่อให้เธรด WASM หลายเธรดเข้าถึงข้อมูลอย่างมีประสิทธิภาพและสอดประสานกัน

SharedArrayBuffer และอะตอมิกสำหรับ WASM เป็นบทเรียน WebAssembly (WASM) for High Performance Apps ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน WebAssembly (WASM) for High Performance Apps และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส WebAssembly (WASM) for High Performance Apps มีบทเรียนทั้งหมด 4 บทเรียน

บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ

Sharing Data Safely in WASM

When building high-performance applications with WebAssembly (WASM), you often need to share data between different parts of your program, especially across multiple threads (Web Workers).

Directly sharing memory can lead to problems like race conditions, where multiple threads try to access and modify the same data at the same time, causing unpredictable results.

This lesson introduces SharedArrayBuffer and atomic operations, essential tools for safe and efficient data sharing in multithreaded WASM applications.

What is SharedArrayBuffer?

A SharedArrayBuffer is a special type of data buffer in JavaScript that can be shared between the main thread and Web Workers.

  • Unlike a regular ArrayBuffer, which can only be transferred (copied) to a worker, a SharedArrayBuffer provides a shared memory space.
  • This means all threads accessing it see the same data at the same time, without needing to copy it back and forth.
  • It's the foundation for enabling true multithreading with WASM in web environments.

JS: Allocating Shared Memory

You create a SharedArrayBuffer on the JavaScript side, just like a regular ArrayBuffer, but using the SharedArrayBuffer constructor.

Once created, you can create typed array views (e.g., Uint32Array) to read and write data. This buffer can then be passed to Web Workers.

Here's how you might set one up in JavaScript:

// In JavaScript:
const sharedBuffer = new SharedArrayBuffer(1024); // 1KB shared memory
const view = new Uint32Array(sharedBuffer); // A view to work with

// Now, 'sharedBuffer' can be passed to Web Workers
// worker.postMessage({ sharedBuffer });

WASM modules loaded in these workers can then access this shared memory.

WASM's View of Shared Memory

When a SharedArrayBuffer is passed to a Web Worker, and a WebAssembly module is instantiated with a WebAssembly.Memory object that uses this shared buffer, the WASM module gains direct access to it.

  • WASM sees this shared memory as its own linear memory.
  • Any reads or writes by the WASM module to its linear memory are directly reflected in the SharedArrayBuffer.
  • This allows WASM instances running in different workers to operate on the exact same data in real-time.

The Problem: Race Conditions

Imagine two Web Workers, each running a WASM module, trying to increment a shared counter in a SharedArrayBuffer.

If both workers read the current value, increment it, and then write it back without coordination, you can have a race condition:

  • Worker A reads 0.
  • Worker B reads 0.
  • Worker A increments 0 to 1 and writes 1.
  • Worker B increments 0 to 1 and writes 1.

The counter should be 2, but it ends up as 1! This is where atomic operations become crucial.

Atomic Operations to the Rescue!

Atomic operations are special instructions that guarantee an operation completes entirely without interruption from other threads.

They are "all or nothing" – either the entire operation finishes successfully, or it doesn't happen at all, preventing partial updates and race conditions.

Key characteristics:

  • Indivisible: Cannot be interrupted by another thread.
  • Guaranteed: Ensures data integrity in concurrent access.
  • Essential: For building reliable multithreaded applications.

Rust: Atomic Increment for WASM

Rust provides atomic types (like AtomicU32, AtomicI64) in its std::sync::atomic module. These can be used when compiling to WebAssembly.

When compiled to WASM, these operations translate to the underlying WebAssembly atomic instructions, which operate safely on shared linear memory.

Here's a simple Rust example demonstrating an atomic counter that could be part of a WASM module:

use std::sync::atomic::{AtomicU32, Ordering};

// A static atomic counter within the WASM module.
// In a full shared memory setup, this would conceptually map
// to an offset within the SharedArrayBuffer passed from JS.
static GLOBAL_COUNTER: AtomicU32 = AtomicU32::new(0);

#[no_mangle]
pub extern "C" fn increment_counter_atomic(amount: u32) -> u32 {
    // Atomically add 'amount' to GLOBAL_COUNTER.
    // Ordering::SeqCst ensures sequential consistency.
    GLOBAL_COUNTER.fetch_add(amount, Ordering::SeqCst);
    // Return the new value (after incrementing)
    GLOBAL_COUNTER.load(Ordering::SeqCst)
}

#[no_mangle]
pub extern "C" fn get_current_counter_atomic() -> u32 {
    // Atomically load the current value.
    GLOBAL_COUNTER.load(Ordering::SeqCst)
}

JS: The Atomics Object

JavaScript also has its own Atomics object, which provides static methods for performing atomic operations directly on SharedArrayBuffer views.

This allows the JavaScript main thread or Web Workers to perform atomic operations on the shared memory, coordinating with WASM modules.

  • Atomics.add(view, index, value): Atomically adds value to the element at index in view.
  • Atomics.load(view, index): Atomically loads the value at index.
  • Atomics.store(view, index, value): Atomically stores value at index.

These methods are crucial for JavaScript to safely interact with WASM's shared memory.

Synchronization with Wait/Notify

Beyond simple read/write operations, Atomics also provides methods for more advanced thread synchronization:

  • Atomics.wait(view, index, expectedValue, timeout): Allows a thread to sleep (block) until a specific memory location (view[index]) no longer holds expectedValue, or a timeout occurs.
  • Atomics.notify(view, index, count): Wakes up one or more threads that are waiting on the specified memory location.

These are powerful tools for building complex multithreaded patterns, like producer-consumer queues, where threads need to pause and resume based on shared data changes.

Building a Concurrent Counter

Combining SharedArrayBuffer and atomic operations, you can build robust concurrent applications. For example, a shared counter:

  • JavaScript: Creates a SharedArrayBuffer and an Uint32Array view.
  • Web Workers: Each worker receives the SharedArrayBuffer and instantiates a WASM module.
  • WASM Module: The WASM code (like our Rust example) uses atomic operations to increment a specific index within its linear memory, which is backed by the SharedArrayBuffer.

This setup ensures that even with multiple threads rapidly incrementing the counter, the final value will always be correct, free from race conditions.

Check Your Understanding

What are the key benefits of using SharedArrayBuffer and atomic operations in WebAssembly?

Recap: Shared Memory & Atomics

We've explored how SharedArrayBuffer enables true shared memory between JavaScript threads and WebAssembly modules, paving the way for multithreaded WASM applications.

Crucially, we learned that atomic operations are indispensable for safely managing this shared memory, preventing race conditions and ensuring data consistency when multiple threads access and modify the same data concurrently.

Mastering these concepts is vital for building high-performance, reliable WebAssembly applications that leverage the full power of modern multi-core processors.

คำถามที่พบบ่อย

บทเรียน “SharedArrayBuffer และอะตอมิกสำหรับ WASM” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “SharedArrayBuffer และอะตอมิกสำหรับ WASM” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส WebAssembly (WASM) for High Performance Apps ให้อัปเกรดเป็น CoddyKit PRO คอร์ส WebAssembly (WASM) for High Performance Apps มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “SharedArrayBuffer และอะตอมิกสำหรับ WASM”

ใช้ SharedArrayBuffer และการดำเนินการแบบอะตอมิกเพื่อให้เธรด WASM หลายเธรดเข้าถึงข้อมูลอย่างมีประสิทธิภาพและสอดประสานกัน คุณปฏิบัติ WebAssembly (WASM) for High Performance Apps ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน WebAssembly (WASM) for High Performance Apps หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน WebAssembly (WASM) for High Performance Apps บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “SharedArrayBuffer และอะตอมิกสำหรับ WASM” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน WebAssembly (WASM) for High Performance Apps นี้ได้ไหม

ได้ บทเรียน WebAssembly (WASM) for High Performance Apps ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. Web Workers พร้อมเธรด WASM
  2. SharedArrayBuffer และอะตอมิกสำหรับ WASM
  3. การออกแบบแอปพลิเคชัน WASM แบบทำงานพร้อมกัน
  4. การส่งข้อความและช่องทางระหว่างเธรด WASM
← กลับไปที่ WebAssembly (WASM) for High Performance Apps