English 中文(简体)
如何在同时使用高原期间锁定/同步访问 Go 变量?
原标题:How to lock/synchronize access to a variable in Go during concurrent goroutines?
  • 时间:2012-05-23 22:41:13
  •  标签:
  • go
  • goroutine

In his answer to this question: Golang for Windows erratic behavior? user @distributed recommended to lock/synchronize access to a shared variable on concurrent goroutines.

我怎样才能做到呢?

有关这个问题的更多情况是:

我得到这个代码( 返回函数, 在 < code> views 上关闭), 同时运行于多个网路 :

func makeHomeHandler() func(c *http.Conn, r *http.Request) {
    views := 1
    return func(c *http.Conn, r *http.Request) {
        fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views)
        views++
    }
}

看来IO函数需要时间, 结果我得到这样的输出:

Counting monkeys, 5 so far.
Counting monkeys, 5 so far.
Counting monkeys, 5 so far.
Counting monkeys, 8 so far.
Counting monkeys, 8 so far.
Counting monkeys, 8 so far.
Counting monkeys, 11 so far.

它的增量是细的, 但是当它得到打印......我可以看到,操作 印刷+加速 完全不是原子。

如果我改成:

func makeHomeHandler() func(c *http.Conn, r *http.Request) {
    views := 0
    return func(c *http.Conn, r *http.Request) {
        views++
        // I can only hope that other goroutine does not increment the counter 
        // at this point, i.e., right after the previous line and before the 
        // next one are executed!
        views_now := views
        fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views_now)
    }
}

似乎还行 但我不能完全确定它是否会最终失败...

最佳回答

如果同步计数器是您想要的, 那么使用 < code> sync. Mutex 是卡通溶液。 同步/ 原子套件只应用于低级别的东西, 或者当您测量到严重的性能问题时 。

type Counter struct {
    mu  sync.Mutex
    x   int64
}

func (c *Counter) Add(x int64) {
    c.mu.Lock()
    c.x += x
    c.mu.Unlock()
}

func (c *Counter) Value() (x int64) {
    c.mu.Lock()
    x = c.x
    c.mu.Unlock()
    return
}

func makeHomeHandler() func(c http.ResponseWriter, r *http.Request) {
    var views Counter
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Counting %s, %d so far.", r.URL.Path[1:], views.Value())
        views.Add(1)
    }
}

对于您的特殊问题,我建议定义一种满足 http.Handler 界面的新类型, 而不是返回关闭。 这看起来更简单 :

type homeHandler struct {
    mu  sync.Mutex
    views   int64
}

func (h *homeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    h.mu.Lock()
    defer h.mu.Unlock()
    fmt.Fprintf(w, "Counting %s, %d so far.", r.URL.Path[1:], h.views)
    h.views++
}

func init() {
    http.Handle("/", new(homeHandler))
}
问题回答

< a href=>" "http://golang.org/pkg/sync/">sync 软件包有一些同步原始数据, 取决于您使用RWMutex 或普通 Mutex 的问题 。

如果您想要更具体的答案,请提供更多关于答案的更多信息。

编辑 : 在阅读链接的问题后, 您可能会重新查找 < a href=> "http://golang. org/ pkg/ sync/toomic>sync/toomic , 尽管 Mutex也很好 。

第2版:我看到你用一个例子更新了文章。这里是使用同步/解剖的代码。

func makeHomeHandler() func(w http.ResponseWriter, r *http.Request) {
    var views *uint64 = new(uint64)
    atomic.StoreUint64(views, 0) // I don t think this is strictly necessary
    return func(w http.ResponseWriter, r *http.Request) {
        // Atomically add one to views and get the new value
        // Perhaps you want to subtract one here
        views_now := atomic.AddUint64(views, 1) 
        fmt.Fprintf(w, "Counting %s, %d so far.", r.URL.Path[1:], views_now)
    }
}

(注:我还没有测试上述内容,所以可能有伤寒/脑膜炎) 我现在测试过。





相关问题
minimum work size of a goroutine [closed]

Does anyone know approximately what the minimum work size is needed in order for a goroutine to be beneficial (assuming that there are free cores for the work to be offloaded to)?

How do you get the terminal size in Go?

How do I get the terminal size in Go. In C it would look like this: struct ttysize ts; ioctl(0, TIOCGWINSZ, &ts); But how to i access TIOCGWINSZ in Go

What do you use to write Go [closed]

I know its a bit too early, but I ve been trying out Go (Google s Programming Language) and its kindof annoying to write code in gedit. So, my question: What do you use to experiment with Go?

Shared memory vs. Go channel communication

One of Go s slogans is Do not communicate by sharing memory; instead, share memory by communicating. I am wondering whether Go allows two different Go-compiled binaries running on the same machine to ...

Embedding instead of inheritance in Go

What is your opinion of this design decision? What advantages does it have and what disadvantages? Links: Embedding description

热门标签