【问题标题】:What's wrong with my golang code? [duplicate]我的 golang 代码有什么问题? [复制]
【发布时间】:2012-09-07 08:18:58
【问题描述】:

可能重复:
Why my golang lock free queue always stuck there?

这是我的完整源代码:

package main

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

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
}
// constructor
func New() (q *Queue) {
    queue := new(Queue)
    queue.head = unsafe.Pointer(new(Node))
    queue.tail = queue.head
    return queue
}
// 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 atomic.CompareAndSwapPointer(&next, nil, newValue) {
            atomic.CompareAndSwapPointer(&self.tail, tail, newValue)
            break
        }else{
            for next != nil {
                tail = next
            }
        }
    }
}

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

func main() {
    //runtime.GOMAXPROCS(runtime.NumCPU())
    fmt.Println(runtime.GOMAXPROCS(-1))
    var wg sync.WaitGroup
    wg.Add(20)
    queue := New()
    for i := 0; i < 10; i++ {
        go func() {
            defer wg.Done()
            for j := 0; j < MAX_DATA_SIZE; j++ {
                t := time.Now()
                fmt.Println("enqueue111")
                fmt.Println("enq = ", t)
                fmt.Println("enqueue222")
                queue.enQueue(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()
}

代码卡在 fmt.Println("enq = ", t) 但不知道为什么,太奇怪了。

【问题讨论】:

  • 请(始终)使代码可编译。那么有人可以帮助你。
  • @jnml 谢谢你的提醒,我已经把整个源代码贴出来了。

标签: go


【解决方案1】:

deQueue 在失败情况下无限循环,这会阻塞 CPU。 Goroutines 在做 CPU 工作时不会屈服。 GOMAXPROCS 需要 >= 2 才能获得 CPU 并行度。

只是为了好玩,这是一个使用高阶通道的线程安全、非阻塞队列实现:https://gist.github.com/3668150

【讨论】:

    【解决方案2】:

    我认为出队 goroutine 一直在运行,试图从一个空队列中出队,而入队 goroutine 则处于饥饿状态。也许尝试使出队阻塞以使入队有机会运行?如果这不仅仅是为了教育价值,我会使用channels。

    编辑:使用渠道的等效版本

    package main
    
    import (
        "sync"
        "fmt"
        "time"
        "runtime"
    )
    
    const (
        MAX_DATA_SIZE = 100
    )
    
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        fmt.Println(runtime.GOMAXPROCS(-1))
        var wg sync.WaitGroup
        wg.Add(20)
        queue := make(chan interface{})
        for i := 0; i < 10; i++ {
            go func() {
                defer wg.Done()
                for j := 0; j < MAX_DATA_SIZE; j++ {
                    t := time.Now()
                    queue <- t
                }
            }()
        }
    
        for i := 0; i < 10; i++ {
            go func() {
                var val interface{}
                defer wg.Done()
                for j := 0; j < MAX_DATA_SIZE; j++ {
                    val = <- queue
                    fmt.Println("deq = ",val)
                }
            }()
        }
    
        wg.Wait()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-28
      • 1970-01-01
      • 2017-04-30
      • 2011-07-28
      相关资源
      最近更新 更多