• GO实现无锁队列


    在使用Go进行多线程开发时,通常通过给队列加锁的方式避免并发读写带来的数据丢失或重复读取等问题,但在高并发条件下,加锁带来的性能降低也是必然的,因此希望通过实现lock-free queue 的算法实现无锁队列,提高程序性能。

    通过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同时更新同一个变量时,只有其中一个线程能更新变量的值,
    而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

  • 相关阅读:
    带有数字的表达式
    不使用data-ng-app指令的表达式
    简单的表达式
    第一个AngularJS控制器
    第一个AngularJS指令
    第一个AngularJS表达式实例
    HTML5<fieldset>标签
    AngularJS 包含
    [python][odlboy]设置字符串打印的颜色
    [python][oldboy]关键字参数和位置参数,默认参数,可变长参数(无名,有名)
  • 原文地址:https://www.cnblogs.com/yourstars/p/15186558.html
Copyright © 2020-2023  润新知