Golang/Gopher在不同通道中操作数据的方式是什么?

huangapple go评论79阅读模式
英文:

Golang/Gopher way to manipulate data in different channels?

问题

你好!以下是翻译好的内容:

我刚开始学习Go语言,并且想确保我在使用通道和并发时没有出错。我有一个结构体:

type Playlist struct {
  playlist   []*Song
  updateList chan *Song
}

我有两个函数在不同的Go协程中操作数据。

第一个函数是在通道上接收到一个歌曲指针时,将数据追加到播放列表中:

func (p *Playlist) continuousUpdate() {
  go func() {
    for newSong := range p.updateList {
      p.playlist = append(p.playlist, newSong)
    }
  }()
}

第二个函数是每隔24小时会触发一个定时器,将播放列表重置为空切片:

func (p *Playlist) controlCurrentPlayList(c <-chan time.Time) {
  go func() {
    for {
      <-c
      p.playlist = make([]*Song, 0)
      log.Println("当前播放列表已重置")
    }
  }()
}

这两个独立的通道是否能够同步数据?或者我很容易遇到竞态条件吗?

我运行了go build -race命令,没有出现错误。

英文:

New to go and to make sure Im on the right page with channels + concurrency I have a struct

type Playlist struct {
  playList   []*Song
  updateList chan *Song
}

I have 2 functions that manipulate the data in separate go routines.

First one is to append data to the playlist whenever a pointer to a song is sent on the channel:

  func (p *Playlist) continuousUpdate() {
	go func (){
      for newSong := range p.updateList {
	    p.playlist = append(p.playlist, newSong)
      }
    }()
  }

And the second one, every 24 hours a timer will tick, thus resetting the playlist to an empty slice.

func (p *Playlist) controlCurrentPlayList(c &lt;-chan time.Time) {
  go func(){
    for {
	  &lt;-c
	  p.playlist = make([]*Song, 0)
	  log.Println(&quot;Current playlist has reset&quot;)
    }
  }()
}

Do two separate channels handle the synchronization of the data? Or could I very easily run into a race condition?

Ran go build -race and no errors appeared.

答案1

得分: 6

因为字段playlist在两个goroutine中没有同步地访问,所以存在竞争条件。

竞争检测器在运行时检测竞争条件,而不是在构建时。这个竞争条件直到24小时的重置计时器触发时才会被检测到。

可以通过使用select语句将这两个goroutine合并来消除竞争条件:

for {
    select {
    case newSong := <-p.updateList:
        p.playlist = append(p.playlist, newSong)
    case <-c:
        p.playlist = make([]*Song, 0)
        log.Println("当前播放列表已重置")
    }
}
英文:

Because the field playlist is accessed from two goroutines with no synchronization, there is a race.

The race detector detects races at runtime, not build time. This race will not be detected until the 24 hour reset timer ticks.

The race can be eliminated by combining the two goroutines using a select statement:

for {
    select {
    case newSong := &lt;-p.updateList:
        p.playlist = append(p.playlist, newSong)
    case &lt;-c:
        p.playlist = make([]*Song, 0)
        log.Println(&quot;Current playlist has reset&quot;)
    }
 }

huangapple
  • 本文由 发表于 2015年8月13日 06:23:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/31976420.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定