package queue
import (
"sync/atomic"
"unsafe"
)
// 無鎖隊(duì)列
type Queue struct {
head, tail unsafe.Pointer
size int32
}
type Node struct {
value any
next unsafe.Pointer
}
func (q *Queue) Enqueue(value any) {
n := &Node{value: value}
retry:
tail := load(&q.tail)
next := load(&tail.next)
if tail == load(&q.tail) {
//如果next為空,則表示tail節(jié)點(diǎn)是隊(duì)列中的最后一個(gè)節(jié)點(diǎn),
//代碼嘗試將新節(jié)點(diǎn)n鏈接到隊(duì)列的尾部,然后將tail指針向前移動(dòng)到新添加的節(jié)點(diǎn)
if next == nil {
if cas(&tail.next, next, n) {
cas(&q.tail, tail, n)
atomic.AddInt32(&q.size, 1)
return
}
} else {
//如果next不為空,表示tail節(jié)點(diǎn)并不是指向隊(duì)列中的最后一個(gè)節(jié)點(diǎn),此時(shí)代碼嘗試將tail指針向前移動(dòng)到下一個(gè)節(jié)點(diǎn)。
cas(&q.tail, tail, next)
}
}
goto retry
}
func (q *Queue) Dequeue() any {
retry:
head := load(&q.head)
tail := load(&q.tail)
next := load(&head.next)
if head == load(&q.head) {
if head == tail {
if next == nil {
return nil
}
cas(&q.tail, tail, next)
} else {
//此行不能省略,在CAS之前讀取,否則會被另一個(gè)dequeue操作修改
value := next.value
if cas(&q.head, head, next) {
atomic.AddInt32(&q.size, -1)
return value
}
}
}
goto retry
}
func (q *Queue) IsEmpty() bool {
return atomic.LoadInt32(&q.size) == 0
}
func load(p *unsafe.Pointer) *Node {
return (*Node)(atomic.LoadPointer(p))
}
func cas(p *unsafe.Pointer, old, new *Node) bool {
return atomic.CompareAndSwapPointer(p, unsafe.Pointer(old), unsafe.Pointer(new))
}
go無鎖隊(duì)列
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。