面试题答案
一键面试- 使用
sync.Mutex
避免资源竞争:sync.Mutex
是Go语言中用于实现互斥锁的工具。当多个Future
任务访问和修改共享资源时,通过在访问共享资源前后加锁和解锁,可以避免资源竞争。- 示例代码:
package main
import (
"fmt"
"sync"
)
var (
sharedResource int
mu sync.Mutex
)
func futureTask(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
sharedResource++
mu.Unlock()
}
func main() {
var wg sync.WaitGroup
numTasks := 10
for i := 0; i < numTasks; i++ {
wg.Add(1)
go futureTask(&wg)
}
wg.Wait()
fmt.Println("Final value of shared resource:", sharedResource)
}
- 使用
sync.RWMutex
优化读操作:- 如果共享资源读操作远多于写操作,可以使用
sync.RWMutex
。它允许多个读操作同时进行,但写操作时需要独占锁。 - 示例代码:
- 如果共享资源读操作远多于写操作,可以使用
package main
import (
"fmt"
"sync"
)
var (
sharedData int
rwMutex sync.RWMutex
)
func readTask(wg *sync.WaitGroup) {
defer wg.Done()
rwMutex.RLock()
fmt.Println("Read value:", sharedData)
rwMutex.RUnlock()
}
func writeTask(wg *sync.WaitGroup) {
defer wg.Done()
rwMutex.Lock()
sharedData++
rwMutex.Unlock()
}
func main() {
var wg sync.WaitGroup
numReadTasks := 5
numWriteTasks := 3
for i := 0; i < numReadTasks; i++ {
wg.Add(1)
go readTask(&wg)
}
for i := 0; i < numWriteTasks; i++ {
wg.Add(1)
go writeTask(&wg)
}
wg.Wait()
}
- 设计数据结构和算法保证数据一致性:
- 数据结构方面:可以将共享资源封装在一个结构体中,并将锁作为结构体的一个字段,这样可以更好地管理对共享资源的访问。
- 算法方面:合理设计任务执行顺序,避免出现循环依赖导致死锁。例如,为每个任务分配一个唯一的ID,按照ID的顺序获取锁等。
- 示例代码(封装共享资源和锁):
package main
import (
"fmt"
"sync"
)
type SharedResource struct {
data int
mu sync.Mutex
}
func (sr *SharedResource) increment(wg *sync.WaitGroup) {
defer wg.Done()
sr.mu.Lock()
sr.data++
sr.mu.Unlock()
}
func main() {
var wg sync.WaitGroup
shared := SharedResource{}
numTasks := 10
for i := 0; i < numTasks; i++ {
wg.Add(1)
go shared.increment(&wg)
}
wg.Wait()
fmt.Println("Final value of shared data:", shared.data)
}
- 使用
sync.Cond
避免死锁:sync.Cond
用于在条件变量上等待或唤醒其他协程。当一个Future
任务需要等待某个条件满足才能继续执行时,可以使用它。- 示例代码:
package main
import (
"fmt"
"sync"
"time"
)
var (
condition sync.Cond
ready bool
)
func task1(wg *sync.WaitGroup) {
defer wg.Done()
condition.L.Lock()
for!ready {
condition.Wait()
}
fmt.Println("Task 1 continues after condition is met")
condition.L.Unlock()
}
func task2(wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(2 * time.Second)
condition.L.Lock()
ready = true
condition.Broadcast()
condition.L.Unlock()
}
func main() {
var wg sync.WaitGroup
var mu sync.Mutex
condition = sync.Cond{L: &mu}
wg.Add(2)
go task1(&wg)
go task2(&wg)
wg.Wait()
}
通过这些策略,使用sync
包中的工具,合理设计数据结构和算法,可以有效地避免在Go的Future
模式高并发编程中出现资源竞争和死锁的问题。