可能出现的内存管理问题
- 竞态条件:多个goroutine同时读写共享内存中的指针指向的数据,会导致数据竞争,最终结果不可预测。例如一个goroutine读取数据时,另一个goroutine同时在修改该数据,可能导致读取到不一致的数据。
使用sync包解决问题
- 使用
sync.Mutex
:
sync.Mutex
用于保护共享资源,确保同一时间只有一个goroutine能够访问共享内存。
package main
import (
"fmt"
"sync"
)
type Data struct {
value int
}
var mu sync.Mutex
var dataPtr *Data
func modifyData(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
if dataPtr == nil {
dataPtr = &Data{value: 0}
}
dataPtr.value++
mu.Unlock()
}
func main() {
var wg sync.WaitGroup
numGoroutines := 10
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go modifyData(&wg)
}
wg.Wait()
mu.Lock()
fmt.Printf("Final value: %d\n", dataPtr.value)
mu.Unlock()
}
- 使用
sync.RWMutex
:
如果读操作远多于写操作,可以使用sync.RWMutex
。它允许多个goroutine同时进行读操作,但写操作时会独占资源。
package main
import (
"fmt"
"sync"
)
type Data struct {
value int
}
var rwmu sync.RWMutex
var dataPtr *Data
func readData(wg *sync.WaitGroup) {
defer wg.Done()
rwmu.RLock()
if dataPtr != nil {
fmt.Printf("Read value: %d\n", dataPtr.value)
}
rwmu.RUnlock()
}
func writeData(wg *sync.WaitGroup) {
defer wg.Done()
rwmu.Lock()
if dataPtr == nil {
dataPtr = &Data{value: 0}
}
dataPtr.value++
rwmu.Unlock()
}
func main() {
var wg sync.WaitGroup
numReaders := 5
numWriters := 3
for i := 0; i < numReaders; i++ {
wg.Add(1)
go readData(&wg)
}
for i := 0; i < numWriters; i++ {
wg.Add(1)
go writeData(&wg)
}
wg.Wait()
}