英文:
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 <-chan time.Time) {
go func(){
for {
<-c
p.playlist = make([]*Song, 0)
log.Println("Current playlist has reset")
}
}()
}
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 := <-p.updateList:
p.playlist = append(p.playlist, newSong)
case <-c:
p.playlist = make([]*Song, 0)
log.Println("Current playlist has reset")
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论