doujiu3095 2014-07-15 06:28
浏览 52
已采纳

同时写入和读取数组的最惯用方式

I have one array that gets modified a few times per second with one goroutine. In another function, I read a random value from the array once every few seconds. What would be the most Go-like way of approaching this problem?

In Java, for example, I would lock the array first and then read from it. I'm not sure if I could use channels for this because I don't want to wait until my other function reads before I can continue updating the array.

package main

import (
    "fmt"
    "math/rand"
    "time"
)

const (
    SliceLength = 32
)

var mySlice []int

func randInt(min int, max int) int {
    return min + rand.Intn(max-min)
}

func writeSlice() {
    for index, _ := range mySlice {
        mySlice[index] = rand.Intn(100)
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    mySlice = make([]int, SliceLength)

    // First time just to populate it.
    writeSlice()

    // Write to the slice.
    go func() {
        for {
            time.Sleep(time.Duration(randInt(10, 50)) * time.Millisecond)
            writeSlice()
        }
    }()

    // Read from slice.
    for {
        time.Sleep(time.Duration(randInt(1, 5)) * time.Second)
        fmt.Println(mySlice[randInt(0, SliceLength)])
    }
}
  • 写回答

2条回答 默认 最新

  • duanao2585 2014-07-16 15:50
    关注

    A mutex sync.RWMutex can work here. You simply share your slice between two goroutines, locking and releasing before/after each slice operation.

    Whilst you're exploring possibilities, you should also consider what the "shared-nothing" principle would mean. You would want to find a solution that does not use a mutex and in which each goroutine has private data only - shared-nothing.

    Suppose you had a third goroutine. Think of it as a server. It holds the slice (or any other contended data structure as required). When your first goroutine wants to make a change, it sends a message on a channel to the server, saying "change x to y". When your second goroutine wants to read the data, it might simply read a copy of the data off a channel coming from the server.

    Inside the server, a select statement will choose between incoming update messages and outgoing read messages - bear in mind that the guards can be on either channel inputs or channel outputs, so this is easy to do.

    ...  declare and initialise the slice
    for {
        select {
        case instruction = <-update:
            ...  apply the instruction to the slice
        case output<- slice:
            ...  sent the slice to the consumer
        }
    }
    

    Notice that the server code is itself single-threaded, i.e. there is no shared-memory access to the slice, even though the behaviour overall is concurrent. This is a nice feature of the CSP approach: locally, there is never any need to worry about shared access to data. "Shared-nothing" means what it says.

    Furthermore, you can fully reason about the possible states of such a piece of code locally, without needing global knowledge. This is a BIG benefit.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog