go / expert
Snippet
Sperrfreie Stack-Implementierung über atomare Zeiger
Hochperformaters hochparalleles Datenhandling verzichtet oft auf Mutex-Sperren und nutzt stattdessen Compare-And-Swap (CAS) Anweisungen. Seit Go 1.19 ermöglicht `atomic.Pointer[T]` die Implementierung sperrfreier Strukturen wie den Treiber-Stack ohne `unsafe.Pointer`. Die CAS-Schleife wiederholt die atomare Zeigerersetzung so lange, bis keine Datenrasse (Race Condition) auftritt.
snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package mainimport ("fmt""sync/atomic")type Node[T any] struct {value Tnext *Node[T]}type LockFreeStack[T any] struct {head atomic.Pointer[Node[T]]}func (s *LockFreeStack[T]) Push(val T) {n := &Node[T]{value: val}for {currHead := s.head.Load()n.next = currHeadif s.head.CompareAndSwap(currHead, n) {return}}}func (s *LockFreeStack[T]) Pop() (T, bool) {var zero Tfor {currHead := s.head.Load()if currHead == nil {return zero, false}nextHead := currHead.nextif s.head.CompareAndSwap(currHead, nextHead) {return currHead.value, true}}}func main() {stack := &LockFreeStack[int]{}stack.Push(42)val, _ := stack.Pop()fmt.Println(val)}
Erklärung
1
head atomic.Pointer[Node[T]]
Verwendet den typsicheren atomaren Zeiger-Container von Go zur atomaren Nachverfolgung des Stack-Kopfs.
2
if s.head.CompareAndSwap(currHead, n) {
Führt eine atomare CAS-Instruktion aus, die den Head-Pointer nur aktualisiert, wenn kein anderer Thread ihn gleichzeitig verändert hat.