最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang實(shí)現(xiàn)無(wú)鎖隊(duì)列的三種方式

 更新時(shí)間:2026年04月14日 10:04:00   作者:游學(xué)四方  
本文主要介紹了golang實(shí)現(xiàn)無(wú)鎖隊(duì)列的三種方式,包括基于CAS操作的簡(jiǎn)單有界隊(duì)列、Michael-Scott算法的無(wú)鎖鏈表隊(duì)列及Go簡(jiǎn)化指針操作方法,感興趣的可以了解一下

1. 基于 CAS 的簡(jiǎn)單有界隊(duì)列

使用固定大小的環(huán)形緩沖區(qū),通過(guò)原子索引實(shí)現(xiàn)無(wú)鎖。

package main
import (
	"fmt"
	"sync"
	"sync/atomic"
)
// LockFreeQueue 基于 CAS 的有界無(wú)鎖隊(duì)列
type LockFreeQueue struct {
	buffer []interface{}
	head   uint64 // 讀取位置
	tail   uint64 // 寫(xiě)入位置
	cap    uint64
}
func NewLockFreeQueue(capacity int) *LockFreeQueue {
	return &LockFreeQueue{
		buffer: make([]interface{}, capacity),
		cap:    uint64(capacity),
	}
}
// Enqueue 入隊(duì)
func (q *LockFreeQueue) Enqueue(val interface{}) bool {
	for {
		tail := atomic.LoadUint64(&q.tail)
		head := atomic.LoadUint64(&q.head)
		// 隊(duì)列已滿
		if tail-head >= q.cap {
			return false
		}
		// 嘗試 CAS 更新 tail
		if atomic.CompareAndSwapUint64(&q.tail, tail, tail+1) {
			idx := tail % q.cap
			q.buffer[idx] = val
			return true
		}
		// CAS 失敗,重試
	}
}
// Dequeue 出隊(duì)
func (q *LockFreeQueue) Dequeue() (interface{}, bool) {
	for {
		head := atomic.LoadUint64(&q.head)
		tail := atomic.LoadUint64(&q.tail)
		// 隊(duì)列為空
		if head == tail {
			return nil, false
		}
		// 嘗試 CAS 更新 head
		if atomic.CompareAndSwapUint64(&q.head, head, head+1) {
			idx := head % q.cap
			val := q.buffer[idx]
			q.buffer[idx] = nil // 幫助 GC
			return val, true
		}
		// CAS 失敗,重試
	}
}
func main() {
	q := NewLockFreeQueue(100)
	var wg sync.WaitGroup
	// 生產(chǎn)者
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			for j := 0; j < 100; j++ {
				q.Enqueue(n*100 + j)
			}
		}(i)
	}
	// 消費(fèi)者
	var count int64
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for {
				if val, ok := q.Dequeue(); ok {
					atomic.AddInt64(&count, 1)
					_ = val
				} else {
					// 空隊(duì)列時(shí)短暫休眠避免忙等
					// 實(shí)際生產(chǎn)可用 runtime.Gosched()
				}
			}
		}()
	}
	wg.Wait()
	fmt.Printf("Processed: %d\n", atomic.LoadInt64(&count))
}

2. 無(wú)界鏈表隊(duì)列(Michael-Scott 算法)

經(jīng)典的無(wú)鎖隊(duì)列算法,使用鏈表實(shí)現(xiàn),支持動(dòng)態(tài)擴(kuò)容。

package main
import (
	"fmt"
	"sync"
	"sync/atomic"
	"unsafe"
)
// node 鏈表節(jié)點(diǎn)
type node struct {
	value interface{}
	next  unsafe.Pointer // *node
}
// LockFreeListQueue 基于 Michael-Scott 算法的無(wú)鎖隊(duì)列
type LockFreeListQueue struct {
	head unsafe.Pointer // *node
	tail unsafe.Pointer // *node
}
func NewLockFreeListQueue() *LockFreeListQueue {
	n := unsafe.Pointer(&node{})
	return &LockFreeListQueue{
		head: n,
		tail: n,
	}
}
// Enqueue 入隊(duì)
func (q *LockFreeListQueue) Enqueue(val interface{}) {
	newNode := &node{value: val}
	newNodePtr := unsafe.Pointer(newNode)
	for {
		tail := (*node)(atomic.LoadPointer(&q.tail))
		next := (*node)(atomic.LoadPointer(&tail.next))
		// 再次檢查 tail 是否變化
		if tail != (*node)(atomic.LoadPointer(&q.tail)) {
			continue
		}
		if next == nil {
			// 嘗試將新節(jié)點(diǎn)鏈接到尾部
			if atomic.CompareAndSwapPointer(&tail.next, unsafe.Pointer(nil), newNodePtr) {
				// 嘗試更新 tail 指針
				atomic.CompareAndSwapPointer(&q.tail, unsafe.Pointer(tail), newNodePtr)
				return
			}
		} else {
			// 幫助推進(jìn) tail 指針
			atomic.CompareAndSwapPointer(&q.tail, unsafe.Pointer(tail), unsafe.Pointer(next))
		}
	}
}
// Dequeue 出隊(duì)
func (q *LockFreeListQueue) Dequeue() (interface{}, bool) {
	for {
		head := (*node)(atomic.LoadPointer(&q.head))
		tail := (*node)(atomic.LoadPointer(&q.tail))
		next := (*node)(atomic.LoadPointer(&head.next))
		if head != (*node)(atomic.LoadPointer(&q.head)) {
			continue
		}
		if head == tail {
			if next == nil {
				return nil, false // 空隊(duì)列
			}
			// 幫助推進(jìn) tail
			atomic.CompareAndSwapPointer(&q.tail, unsafe.Pointer(tail), unsafe.Pointer(next))
		} else {
			val := next.value
			if atomic.CompareAndSwapPointer(&q.head, unsafe.Pointer(head), unsafe.Pointer(next)) {
				return val, true
			}
		}
	}
}
func main() {
	q := NewLockFreeListQueue()
	var wg sync.WaitGroup
	var count int64
	// 生產(chǎn)者
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			for j := 0; j < 1000; j++ {
				q.Enqueue(n*1000 + j)
			}
		}(i)
	}
	// 消費(fèi)者
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for {
				if val, ok := q.Dequeue(); ok {
					atomic.AddInt64(&count, 1)
					_ = val
				}
			}
		}()
	}
	wg.Wait()
	fmt.Printf("Total dequeued: %d\n", atomic.LoadInt64(&count))
}

3、使用 sync/atomic 的簡(jiǎn)化版本(Go 1.19+)

Go 1.19 引入了 atomic.Pointer,可以簡(jiǎn)化指針操作:

locklessqueue.go

//locklessqueue.go
package lockless
import (
	"sync/atomic"
)
type LockFreeQueue struct {
	buf  []interface{}
	len  int32
	head int32
	tail int32
}
func NewQueue(n int32) *LockFreeQueue {
	q := &LockFreeQueue{buf: make([]interface{}, n+1, n+1), len: n + 1}
	return q
}
func (s *LockFreeQueue) PushBack(v interface{}) {
	for {
		tail := atomic.LoadInt32(&s.tail)
		n := (tail + 1) % s.len
		if atomic.CompareAndSwapInt32(&s.head, n, n) {
			continue // 隊(duì)列滿了
		}
		if !atomic.CompareAndSwapInt32(&s.tail, tail, n) {
			continue // 獲取失敗
		}
		s.buf[tail] = v
		break
	}
}
func (s *LockFreeQueue) PopFront() interface{} {
	for {
		tail := atomic.LoadInt32(&s.tail)
		head := atomic.LoadInt32(&s.head)
		if tail == head {
			continue
		}
		n := (head + 1) % s.len
		if !atomic.CompareAndSwapInt32(&s.head, head, n) {
			continue
		}
		return s.buf[head]
	}
}

測(cè)試代碼
locklessqueue_test.go

//locklessqueue_test.go
package lockless
import (
	"sync"
	"testing"
)
func TestName(t *testing.T) {
	lq := NewQueue(10)
	w := sync.WaitGroup{}
	for i := 0; i < 100; i++ {
		w.Add(1)
		go func(gi int) {
			lq.PushBack(gi)
			w.Done()
		}(i)
	}
	go func() {
		for {
			lq.PopFront()
			//	time.Sleep(1 * time.Second)
		}
	}()
	w.Wait()
}
var ch = make(chan interface{}, 50000)
func BenchmarkGo_Chan(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ch <- 123
		go func() {
			<-ch
		}()
	}
}
func BenchmarkGo_LockFree(b *testing.B) {
	lq := NewQueue(1000000000)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		lq.PushBack(123)
		go func() {
			lq.PopFront()
		}()
	}
}

執(zhí)行命令

PS D:\golang\src\Test\Test> go test -v   locklessqueue_test.go locklessqueue.go     
=== RUN   TestName
--- PASS: TestName (0.00s)
PASS
ok      command-line-arguments  0.173s

性能測(cè)試

D:\golang\src\Test\Test>  go test -v -bench="." locklessqueue_test.go  locklessqueue.go
=== RUN   TestName
--- PASS: TestName (0.00s)
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-9500F CPU @ 3.00GHz
BenchmarkGo_Chan
BenchmarkGo_Chan-6               2957491               414.7 ns/op
BenchmarkGo_LockFree
BenchmarkGo_LockFree-6           4356723               272.4 ns/op
PASS
ok      command-line-arguments  85.410s

到此這篇關(guān)于golang實(shí)現(xiàn)無(wú)鎖隊(duì)列的文章就介紹到這了,更多相關(guān)golang 無(wú)鎖隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GO語(yǔ)言快速入門(mén)的全面學(xué)習(xí)筆記總結(jié)(實(shí)例代碼)

    GO語(yǔ)言快速入門(mén)的全面學(xué)習(xí)筆記總結(jié)(實(shí)例代碼)

    本博客分享Go語(yǔ)言學(xué)習(xí)筆記總結(jié),助讀者快速掌握基本編碼能力,介紹了Go語(yǔ)言誕生背景、應(yīng)用場(chǎng)景,指出Java等程序員學(xué)習(xí)誤區(qū),還涵蓋環(huán)境搭建、程序結(jié)構(gòu)、常用集合、函數(shù)、面向?qū)ο缶幊?、錯(cuò)誤機(jī)制、包管理和并發(fā)編程等內(nèi)容,并給出代碼示例和驗(yàn)證
    2026-01-01
  • Go語(yǔ)言Zap庫(kù)Logger的定制化和封裝使用詳解

    Go語(yǔ)言Zap庫(kù)Logger的定制化和封裝使用詳解

    這篇文章主要介紹了Go語(yǔ)言Zap庫(kù)Logger的定制化和封裝使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 線上問(wèn)題排查之golang使用json進(jìn)行對(duì)象copy

    線上問(wèn)題排查之golang使用json進(jìn)行對(duì)象copy

    這篇文章主要介紹了線上問(wèn)題排查之golang使用json進(jìn)行對(duì)象copy,文章圍繞golang使用json進(jìn)行對(duì)象copy的內(nèi)存溢出問(wèn)題排查展開(kāi)詳細(xì)內(nèi)容需要的小伙伴可以參考一下
    2022-06-06
  • golang validator庫(kù)參數(shù)校驗(yàn)實(shí)用技巧干貨

    golang validator庫(kù)參數(shù)校驗(yàn)實(shí)用技巧干貨

    這篇文章主要為大家介紹了validator庫(kù)參數(shù)校驗(yàn)實(shí)用技巧干貨,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang學(xué)習(xí)筆記(四):array、slice、map

    Golang學(xué)習(xí)筆記(四):array、slice、map

    這篇文章主要介紹了Golang學(xué)習(xí)筆記(四):array、slice、map,本文分別講解了這3個(gè)類(lèi)型的聲明&賦值、元素訪問(wèn)、其它操作,需要的朋友可以參考下
    2015-05-05
  • Golang中時(shí)間相關(guān)操作合集

    Golang中時(shí)間相關(guān)操作合集

    這篇文章主要為大家介紹了Golang中的各種時(shí)間相關(guān)操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • 詳解Go語(yǔ)言中的內(nèi)存對(duì)齊

    詳解Go語(yǔ)言中的內(nèi)存對(duì)齊

    前面我們學(xué)習(xí)了Go語(yǔ)言空結(jié)構(gòu)體詳解,最近又在看unsafe包的知識(shí),在查閱相關(guān)資料時(shí)不免會(huì)看到內(nèi)存對(duì)齊相關(guān)的內(nèi)容。雖然不會(huì),但可以學(xué)呀,那么這篇文章,我們就一起來(lái)看下什么是內(nèi)存對(duì)齊吧
    2022-10-10
  • 一文帶你掌握Golang中的值類(lèi)型和引用類(lèi)型

    一文帶你掌握Golang中的值類(lèi)型和引用類(lèi)型

    在?Golang?中,數(shù)據(jù)類(lèi)型可以分為兩大類(lèi):值類(lèi)型(Value?Types)和引用類(lèi)型(Reference?Types),理解這兩種類(lèi)型的區(qū)別對(duì)于理解?Golang?中的數(shù)據(jù)傳遞和內(nèi)存管理是很重要的,下面就跟隨小編一起深入了解一下它們吧
    2024-01-01
  • Go 語(yǔ)言中的 Struct Tag 的用法詳解

    Go 語(yǔ)言中的 Struct Tag 的用法詳解

    在 Go 語(yǔ)言中,結(jié)構(gòu)體字段標(biāo)簽(Struct Tag) 是一種用于給字段添加元信息(metadata)的機(jī)制,常用于序列化(如 JSON、XML)、ORM 映射、驗(yàn)證等場(chǎng)景,本文給大家介紹Go 語(yǔ)言中的 Struct Tag 的用法,感興趣的朋友一起看看吧
    2025-05-05
  • golang中接口對(duì)象的轉(zhuǎn)型兩種方式

    golang中接口對(duì)象的轉(zhuǎn)型兩種方式

    這篇文章主要介紹了golang中接口對(duì)象的轉(zhuǎn)型方式,大家都知道接口對(duì)象的轉(zhuǎn)型有兩種方式,文中通過(guò)示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10

最新評(píng)論

成武县| 古田县| 延川县| 麦盖提县| 佛坪县| 滦平县| 通海县| 崇礼县| 宁河县| 安平县| 澎湖县| 丰宁| 类乌齐县| 霍林郭勒市| 乐昌市| 凤山县| 阿合奇县| 横山县| 台江县| 镇原县| 大冶市| 扬中市| 连山| 白朗县| 武隆县| 随州市| 时尚| 志丹县| 长汀县| 道真| 海阳市| 瓦房店市| 巴塘县| 东光县| 蓬莱市| 扎囊县| 霍山县| 托克逊县| 陆川县| 朝阳市| 和田县|