Spots

Concurrency Programming (4): Mutex Implementation — From Runtime to CPU

0. What Does This Article Continue to Answer?

The previous article started from the rules of

The previous article started from the rules of the language memory model and looked at how a Mutex provides Atomicity, Visibility, and Ordering. This article continues downward: how Java, Go, and CPython implement those guarantees at the Runtime and CPU layers. 1. How Does HotSpot Implement synchronized? First, fix the implementation layers for Java: 1.2 The Complete Path of One synchronized Operation

The sequence diagram above keeps only the main

The sequence diagram above keeps only the main cross-layer path. The contention path inside the Runtime can be expanded further: Atomicity corresponds to the two atomic competitions in the flowchart above:

Both atomically modify lock state. When multiple threads

Both atomically modify lock state. When multiple threads compete at the same time, only one thread can successfully acquire the lock and enter the critical section. 1.4 Visibility and Ordering Visibility and Ordering correspond to the lock boundaries in the flowchart:

Release / Acquire connects the two critical sections

Release / Acquire connects the two critical sections so that writes from the previous lock holder can be observed by the next lock holder in the correct order. Going further down, these guarantees are implemented through CPU Cache Coherence and memory-ordering constraints. So Java maps back to the hardware model from the first article as follows:

LOCK ADDL $0, 0(%rsp) is the actual full-fence

LOCK ADDL $0, 0(%rsp) is the actual full-fence path used by HotSpot on Linux x86. This does not mean every synchronized operation executes an extra copy of that instruction; x86 ordering rules and LOCKed RMW operations also participate in establishing the required ordering. 2. How Does the Go Runtime Implement sync.Mutex? 2.2 The Complete Path of One sync.Mutex Operation

The sequence diagram above keeps only the main

The sequence diagram above keeps only the main cross-layer path. The contention path inside sync.Mutex can be expanded further: Atomicity corresponds to the atomic lock-state modifications in the flow above:

When multiple Goroutines compete at the same time

When multiple Goroutines compete at the same time, only one can successfully change state from unlocked to locked and enter the critical section. On amd64, these two classes of atomic operation map to LOCK CMPXCHGL and LOCK XADDL. 2.4 Visibility and Ordering

Visibility and Ordering correspond to the synchronization boundary

Visibility and Ordering correspond to the synchronization boundary formed by Lock / Unlock. After one holder completes Unlock, a later Goroutine that successfully executes Lock can observe writes from the previous critical section in the required order.

Going further down, these guarantees are implemented through

Going further down, these guarantees are implemented through CPU Cache Coherence, x86 memory ordering, and the ordering constraints of the atomic instructions themselves. So Go maps back to the hardware model from the first article as follows:

News

Concurrency Programming (4): Mutex Implementation — From Runtime to CPU

0.

@spots #dev
Source: Dev.to
See more like this