为什么我的golang锁定空闲队列总是停留在那里? [英] Why my golang lock free queue always stuck there?

查看:107
本文介绍了为什么我的golang锁定空闲队列总是停留在那里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我的代码:

 包主
$ b导入(
同步/ atomic
unsafe
sync
fmt
time


const(
MAX_DATA_SIZE = 100


//锁定空闲队列
类型队列结构{
head unsafe.Pointer
tail unsafe.Pointer
}
//队列中的一个节点
类型节点struct {
val interface {}
next unsafe.Pointer
}
//队列函数
func(self * Queue)enQueue(val interface {}){
newValue:= unsafe.Pointer(& Node {val:val,next:nil})
var tail,next unsafe.Pointer
for {
tail = self.tail
next =((* Node)(tail))。next
if next!= nil {
atomic.CompareAndSwapPointer( &((* * Node)(tail).next),nil,newValue){
break
}
}
}

func (self * Queue)deQueue()(val interface {},success bool){
var head,tail,next unsafe.Pointer
for {
head = self.head
tail = self.tail
next =((* Node)(head))。next
if head == tail {
if next == nil {
return nil,false
} else {
atomic.CompareAndSwapPointer(&(self.tail),tail,next)
}
} else {
val =((* Node) (next))。val
if atomic.CompareAndSwapPointer(&(self.head),head,next){
return val,true
}
}
}
return
}

func main(){
var wg sync.WaitGroup
wg.Add(20)
queue:= new(Queue)
queue.head = unsafe.Pointer(new(Node))
queue.tail = queue.head

for i:= 0;我< 10; i ++ {
去func(){
推迟wg.Done()
for j:= 0; j< MAX_DATA_SIZE; j ++ {
t:= time.Now()
queue.enQueue(t)
fmt.Println(enq =,t)
}
}()
}

for i:= 0;我< 10; i ++ {
go func(){
ok:= false
var val interface {}
推迟wg.Done()
for j:= 0; j< MAX_DATA_SIZE; j ++ {
val,ok = queue.deQueue()
!ok {
val,ok = queue.deQueue()
}
fmt.Println( deq =,val)
}
}()
}

wg.Wait()
}



问题是,有时代码可以正常运行,但有时会失败,只是无法响应。



在我的代码中是否有任何问题?

解决方案

@mkb建议(禁止无限队列大小)。

它不会锁定。



d建议您使用渠道,除非您有充分的理由不要因为Go团队花费大量精力使其可靠,高性能且易于使用。



<$
fmt
运行时
同步
时间


co nst(
MAX_DATA_SIZE = 100


func main(){
runtime.GOMAXPROCS(4)
var wg sync.WaitGroup
wg.Add(20)
queue:= make(chan time.Time,10)

for i:= 0;我< 10; i ++ {
去func(){
推迟wg.Done()
for j:= 0; j< MAX_DATA_SIZE; j ++ {
t:= time.Now()
queue< - t
fmt.Println(enq =,t)
}
}()
}

for i:= 0;我< 10; i ++ {
去func(){
推迟wg.Done()
for j:= 0; j< MAX_DATA_SIZE; j ++ {
val:=< -queue
fmt.Println(deq =,val)
}
}()
}

wg.Wait()
}


Here is my code:

package main

import (
    "sync/atomic"
    "unsafe"
    "sync"
    "fmt"
    "time"
)

const (
    MAX_DATA_SIZE = 100
)

// lock free queue
type Queue struct {
    head unsafe.Pointer
    tail unsafe.Pointer
}
// one node in queue
type Node struct {
    val interface{}
    next unsafe.Pointer
}
// queue functions
func (self *Queue) enQueue(val interface{}) {
    newValue := unsafe.Pointer(&Node{val: val, next: nil})
    var tail,next unsafe.Pointer
    for {
        tail = self.tail
        next = ((*Node)(tail)).next
        if next != nil {
            atomic.CompareAndSwapPointer(&(self.tail), tail, next)
        }else if atomic.CompareAndSwapPointer(&((*Node)(tail).next), nil, newValue){
            break
        }
    }
}

func (self *Queue) deQueue() (val interface{}, success bool){
    var head,tail,next unsafe.Pointer
    for {
        head = self.head
        tail = self.tail
        next = ((*Node)(head)).next
        if head == tail {
            if next == nil {
                return nil, false
            }else {
                atomic.CompareAndSwapPointer(&(self.tail), tail, next)
            }
        }else {
            val = ((*Node)(next)).val
            if atomic.CompareAndSwapPointer(&(self.head), head, next) {
                return val, true
            }
        }
    }
    return
}

func main() {
    var wg sync.WaitGroup
    wg.Add(20)
    queue := new(Queue)
    queue.head = unsafe.Pointer(new(Node))
    queue.tail = queue.head

    for i := 0; i < 10; i++ {
        go func() {
            defer wg.Done()
            for j := 0; j < MAX_DATA_SIZE; j++ {
                t := time.Now()
                queue.enQueue(t)
                fmt.Println("enq = ", t)
            }
        }()
    }

    for i := 0; i < 10; i++ {
        go func() {
            ok := false
            var val interface{}
            defer wg.Done()
            for j := 0; j < MAX_DATA_SIZE; j++ {
                val,ok = queue.deQueue()
                for !ok {
                    val,ok = queue.deQueue()
                }
                fmt.Println("deq = ",val)
            }
        }()
    }

    wg.Wait()
}

The problem is, sometimes the code runs ok, but sometimes it fails and just gets stuck with no response.

Is there any problem in my code?

解决方案

Here is the above re-written with channels as @mkb suggested (bar the infinite queue size).

It doesn't lock up.

I'd suggest you use channels unless you have a really good reason not to as the Go team have spend a great deal of effort making them reliable, high performance and easy to use.

package main

import (
    "fmt"
    "runtime"
    "sync"
    "time"
)

const (
    MAX_DATA_SIZE = 100
)

func main() {
    runtime.GOMAXPROCS(4)
    var wg sync.WaitGroup
    wg.Add(20)
    queue := make(chan time.Time, 10)

    for i := 0; i < 10; i++ {
        go func() {
            defer wg.Done()
            for j := 0; j < MAX_DATA_SIZE; j++ {
                t := time.Now()
                queue <- t
                fmt.Println("enq = ", t)
            }
        }()
    }

    for i := 0; i < 10; i++ {
        go func() {
            defer wg.Done()
            for j := 0; j < MAX_DATA_SIZE; j++ {
                val := <-queue
                fmt.Println("deq = ", val)
            }
        }()
    }

    wg.Wait()
}

这篇关于为什么我的golang锁定空闲队列总是停留在那里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆