notes

Log | Files | Refs | README

spinlock.md (6792B)


      1 # Spinlock Mechanism
      2 
      3 A spinlock works by repeatedly "spinning" — checking an atomic `locked` flag in
      4 a tight loop until it successfully flips it from `false` to `true`. The key
      5 operations are:[^1]
      6 
      7 - **`lock()`** — atomically swaps `locked` from `false` to `true`. If `locked`
      8   is _already_ `true`, it keeps retrying (the "spin")
      9 - **`unlock()`** — stores `false` back into `locked`, releasing it for another
     10   thread
     11 
     12 ```
     13 THREAD 1                              THREAD 2
     14 ────────────────────────────────────────────────────────────
     15 
     16   ┌──────────────────────────┐
     17   │  swap locked             │
     18   │  false → true (acquire)  │
     19   └────────────┬─────────────┘
     20 lock()         │
     21     22   ┌──────────────────────────┐        ┌──────────────────────────┐
     23   │    access protected data │        │  swap locked             │
     24   └────────────┬─────────────┘        │  true → true (acquire)   │
     25                │                      └────────────┬─────────────┘
     26 unlock()       │                                   │  (spinning...)
     27                ▼                      ┌────────────▼─────────────┐
     28   ┌──────────────────────────┐        │  swap locked             │
     29   │  store false in locked   │        │  true → true (acquire)   │
     30   │       (release)          │        └────────────┬─────────────┘
     31   └────────────┬─────────────┘                     │  (spinning...)
     32                │                                   │
     33                │  happens-before                   │
     34                └───────────────────────────────────▼
     35                                       ┌──────────────────────────┐
     36                                       │  swap locked             │
     37                                       │  false → true (acquire)  │  ← lock() succeeds
     38                                       └────────────┬─────────────┘
     39                                     lock()         │
     40     41                                       ┌──────────────────────────┐
     42                                       │    access protected data │
     43                                       └────────────┬─────────────┘
     44                                     unlock()       │
     45     46                                       ┌──────────────────────────┐
     47                                       │  store false in locked   │
     48                                       │       (release)          │
     49                                       └──────────────────────────┘
     50 ```
     51 
     52 - Thread 1 (left column) acquires the lock immediately (swaps false → true),
     53   accesses the protected data, then releases by storing false. ​
     54 
     55 - Thread 2 (right column) spins repeatedly — each swap returns true → true,
     56   meaning the lock is still held — until Thread 1's unlock() stores false. ​
     57 
     58 - The happens-before arrow (the pink curved arrow in the original) is shown as
     59   the └──────────────────────────────────────────────────────▶ line connecting
     60   Thread 1's release to Thread 2's successful acquire. This is the critical
     61   guarantee that prevents concurrent data access.
     62 
     63 ## Why the Second Thread is Blocked
     64 
     65 Looking at the diagram, Thread 2 (right column) attempts its own `lock()` call
     66 but keeps getting `true → true` swaps, meaning it sees the lock is still held.
     67 It can only proceed when Thread 1's `unlock()` stores `false` — at that point,
     68 Thread 2's next swap finally succeeds (`false → true`), and _only then_ does it
     69 access the protected data.[^2]
     70 
     71 This is the **happens-before relationship** mentioned in the text: Thread 1's
     72 `unlock()` (release) _happens before_ Thread 2's successful `lock()` (acquire),
     73 which guarantees that any memory writes Thread 1 made to the shared data are
     74 visible to Thread 2.[^3]
     75 
     76 ## The Concrete Guarantee
     77 
     78 | Moment | Thread 1                       | Thread 2                     |
     79 | :----- | :----------------------------- | :--------------------------- |
     80 | T1     | Acquires lock (`false→true`)   | —                            |
     81 | T2     | Accessing protected data       | Spinning (sees `true→true`)  |
     82 | T3     | Releases lock (stores `false`) | Still spinning               |
     83 | T4     | Done                           | Acquires lock (`false→true`) |
     84 | T5     | —                              | Accessing protected data     |
     85 
     86 The data access blocks (pink/maroon boxes in the diagram) are never active at
     87 the same time — Thread 2 is stuck spinning until Thread 1 is completely done and
     88 has unlocked. That's what "can't access the data concurrently" means: the
     89 spinlock enforces **serial, not parallel** access to that critical section.[^1]
     90 <span style="display:none">[^10][^11][^4][^5][^6][^7][^8][^9]</span>
     91 
     92 <div align="center">⁂</div>
     93 
     94 [^1]: https://www.shadecoder.com/topics/a-spinlock-a-comprehensive-guide-for-2025
     95 
     96 [^2]: https://wiki.osdev.org/Spinlock
     97 
     98 [^3]: https://en.wikipedia.org/wiki/Lock_(computer_science)
     99 
    100 [^4]: image.jpg
    101 
    102 [^5]: https://www.productteacher.com/quick-product-tips/understanding-mutual-exclusion-mutex
    103 
    104 [^6]: https://stackoverflow.com/questions/53919851/how-spinlock-prevents-the-process-to-be-interrupted
    105 
    106 [^7]: https://forums.swift.org/t/pitch-synchronous-mutual-exclusion-lock/69889
    107 
    108 [^8]: https://student.cs.uwaterloo.ca/~cs350/F19/notes/synchronization-2up.pdf
    109 
    110 [^9]: https://student.cs.uwaterloo.ca/~cs350/F20/notes/synchronization-2up.pdf
    111 
    112 [^10]: https://de.wikipedia.org/wiki/Spinlock
    113 
    114 [^11]: https://spcl.inf.ethz.ch/Teaching/2020-pp/lectures/PP-l17-BeyondLocks.pdf