在线时间:8:00-16:00
132-9538-2358
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
通过lock-free queue ,实现无锁队列,进而提升Go程序性能。
随着并发数越高,无锁队列的执行效率越高。
详细方案:
引用atomic包,实现lock-free queue 算法(Compare and swap),实现无锁队列:
package queue import ( "sync/atomic" "unsafe" ) // 定义无锁队列结构 type LKQueue struct { head unsafe.Pointer tail unsafe.Pointer } type node struct { value interface{} next unsafe.Pointer } // 新建队列,返回一个空队列 func NewLKQueue() *LKQueue { n := unsafe.Pointer(&node{}) return &LKQueue{head: n, tail: n} } // 插入,将给定的值v放在队列的尾部 func (q *LKQueue) Enqueue(v interface{}) { n := &node{value: v} for { tail := load(&q.tail) next := load(&tail.next) if tail == load(&q.tail) { if next == nil { if cas(&tail.next, next, n) { cas(&q.tail, tail, n) // 排队完成, 尝试将tail移到插入的节点 return } } else { // tail没有指向最后一个节点 // 将Tail移到下一个节点 cas(&q.tail, tail, next) } } } } // 移除,删除并返回队列头部的值,如果队列为空,则返回nil func (q *LKQueue) Dequeue() interface{} { for { 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之前读取值,否则另一个出队列可能释放下一个节点 v := next.value if cas(&q.head, head, next) { return v } } } } } func load(p *unsafe.Pointer) (n *node) { return (*node)(atomic.LoadPointer(p)) } // CAS算法 func cas(p *unsafe.Pointer, old, new *node) (ok bool) { return atomic.CompareAndSwapPointer( p, unsafe.Pointer(old), unsafe.Pointer(new)) }
理解CAS算法的含义,大致为:
当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
评论
请发表评论