78 lines
1.5 KiB
Go
78 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
"unsafe"
|
|
)
|
|
|
|
type node struct {
|
|
value interface{}
|
|
next unsafe.Pointer
|
|
}
|
|
|
|
type LockFreeStack struct {
|
|
top unsafe.Pointer
|
|
}
|
|
|
|
func (s *LockFreeStack) Push(v interface{}) {
|
|
newNode := &node{value: v}
|
|
for {
|
|
oldTop := atomic.LoadPointer(&s.top)
|
|
newNode.next = oldTop
|
|
if atomic.CompareAndSwapPointer(&s.top, oldTop, unsafe.Pointer(newNode)) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *LockFreeStack) Pop() (interface{}, bool) {
|
|
for {
|
|
oldTop := atomic.LoadPointer(&s.top)
|
|
if oldTop == nil {
|
|
return nil, false // 栈空:返回 false
|
|
}
|
|
node := (*node)(oldTop)
|
|
if atomic.CompareAndSwapPointer(&s.top, oldTop, node.next) {
|
|
return node.value, true // 弹出成功:返回 true
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
stack := &LockFreeStack{}
|
|
var wg sync.WaitGroup
|
|
const ops = 1000
|
|
|
|
wg.Add(2)
|
|
// 生产者:压入 1000 个元素
|
|
go func() {
|
|
defer wg.Done()
|
|
for i := 0; i < ops; i++ {
|
|
stack.Push(i)
|
|
}
|
|
}()
|
|
|
|
// 消费者:弹出 1000 个元素
|
|
go func() {
|
|
defer wg.Done()
|
|
count := 0
|
|
for count < ops {
|
|
if _, ok := stack.Pop(); ok {
|
|
count++
|
|
}
|
|
}
|
|
}()
|
|
|
|
wg.Wait()
|
|
|
|
// 🔑 核心修正:验证栈是否为空
|
|
_, popped := stack.Pop() // popped = true 表示"成功弹出"(栈非空)
|
|
if !popped { // !popped = true 表示"弹出失败"(栈已空)✅
|
|
fmt.Println("✅ 无锁栈验证通过:所有元素正确入栈出栈,栈已空")
|
|
} else {
|
|
fmt.Println("❌ 栈非空,存在数据不一致(验证逻辑已修正)")
|
|
}
|
|
}
|