dongyuans61046 2012-09-06 01:52
浏览 146
已采纳

为什么我的golang无锁队列总是停在那里?

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?

  • 写回答

2条回答 默认 最新

  • duanrong5927 2012-09-06 18:23
    关注

    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()
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥200 wsl2 vllm qwen1.5部署问题
  • ¥100 有偿求数字经济对经贸的影响机制的一个数学模型,弄不出来已经快要碎掉了
  • ¥15 这个公式写进SIMULINK中的function模块的代码中应该是什么样的
  • ¥15 javaweb登陆的网页为什么不能正确连接查询数据库
  • ¥15 数学建模数学建模需要
  • ¥15 已知许多点位,想通过高斯分布来随机选择固定数量的点位怎么改
  • ¥20 nao机器人语音识别问题
  • ¥15 怎么生成确定数目的泊松点过程
  • ¥15 layui数据表格多次重载的数据覆盖问题
  • ¥15 python点云生成mesh精度不够怎么办