面试题答案
一键面试- 原理:
- Go语言中通过
channel
进行数据传递本身就提供了一种同步机制。channel
是类型化的管道,在多个goroutine之间传递数据时,发送操作(<-
左边)和接收操作(<-
右边)是同步的。当一个goroutine向channel
发送数据时,它会阻塞,直到另一个goroutine从该channel
接收数据;反之,当一个goroutine从channel
接收数据时,它也会阻塞,直到有数据被发送到该channel
。这就避免了多个goroutine同时访问和修改同一数据的情况,从而保证了数据的一致性。 - 除了
channel
,Go还提供了sync
包中的一些同步原语,如Mutex
(互斥锁)、WaitGroup
等,也可以用于解决数据竞争问题。Mutex
用于保护共享资源,保证同一时间只有一个goroutine可以访问共享资源;WaitGroup
用于等待一组goroutine完成任务。
- Go语言中通过
- 可能用到的同步机制:
channel
:作为Go语言并发编程的核心机制,用于在goroutine之间安全地传递数据。Mutex
:互斥锁,用于保护共享资源,防止多个goroutine同时访问。WaitGroup
:用于等待一组goroutine完成工作,确保在所有相关goroutine完成操作后再进行后续处理。
- 示例代码:
package main
import (
"fmt"
"sync"
)
// 定义一个结构体来表示共享数据
type SharedData struct {
value int
mu sync.Mutex
}
// 函数用于修改共享数据
func modifyData(data *SharedData, wg *sync.WaitGroup, ch chan struct{}) {
defer wg.Done()
// 使用channel来同步开始修改操作
<-ch
data.mu.Lock()
data.value++
data.mu.Unlock()
}
func main() {
var wg sync.WaitGroup
sharedData := SharedData{value: 0}
ch := make(chan struct{})
// 启动多个goroutine
for i := 0; i < 5; i++ {
wg.Add(1)
go modifyData(&sharedData, &wg, ch)
}
// 发送信号给所有goroutine开始执行
for i := 0; i < 5; i++ {
ch <- struct{}{}
}
close(ch)
// 等待所有goroutine完成
wg.Wait()
fmt.Println("Final value:", sharedData.value)
}
在这个示例中:
- 我们定义了一个
SharedData
结构体,其中包含一个共享的整数值value
和一个Mutex
来保护这个值。 modifyData
函数是一个goroutine执行的函数,它通过从channel
接收信号来开始操作,使用Mutex
锁定共享数据,修改数据后解锁。- 在
main
函数中,我们创建了一个WaitGroup
来等待所有goroutine完成,一个channel
来同步启动所有goroutine的修改操作。启动5个goroutine,然后通过channel
发送信号让它们开始工作,最后等待所有goroutine完成并打印最终的共享数据值。这样就确保了在并发环境下数据的一致性并避免了数据竞争问题。