var (
sum = 0
wg sync.WaitGroup
)
func incr() {
defer wg.Done()
for i := 0; i < 100000;i++ {
sum++
}
}
func main() {
wg.Add(2)
go incr()
go incr()
wg.Wait()
fmt.Println(sum)
}
我们的目标是输出 sum = 200000,但是结果并不理想。因为 sum 是全局变量,会被两个 goroutine 操作,在操作的过程中可能会出现一个 goroutine 覆盖另一个 goroutine 值的情况出现。
我们下边可以利用两种方法来解决:
sync.mutex 加锁
var (
sum = 0
mutex sync.Mutex
wg sync.WaitGroup
)
func incr() {
defer wg.Done()
for i := 0; i < 100000;i++ {
mutex.Lock()
{
sum++
}
mutex.Unlock()
}
}
func main() {
wg.Add(2)
go incr()
go incr()
wg.Wait()
fmt.Println(sum)
}
我们在对 sum 进行操作的时候加锁,防止出现并发安全问题
atomic
var (
sum int32
wg sync.WaitGroup
)
func incr() {
defer wg.Done()
for i := 0; i < 100000;i++ {
atomic.AddInt32(&sum, 1)
}
}
func main() {
wg.Add(2)
go incr()
go incr()
wg.Wait()
fmt.Println(sum)
}
我们使用 atomic 包对 sum 进行安全的并发操作
mutex in struct
如下代码:
type User struct {
sync.Mutex
Name string
Age int
}
func userSleep(user *User) {
defer w.Done()
user.Lock()
fmt.Println(user.Name + " sleeping...")
time.Sleep(5 * time.Second)
fmt.Println(user.Name + " wake up.")
user.Unlock()
}
var (
w sync.WaitGroup
)
func main() {
u1 := User{
Name: "Tom",
Age: 23,
}
w.Add(2)
go userSleep(&u1)
go userSleep(&u1)
w.Wait()
}
输出:
Tom sleeping...
// Sleep 5s
Tom wake up.
Tom sleeping...
// Sleep 5s
Tom wake up.
type User struct {
sync.Mutex
Name string
Age int
}
type Male struct {
User
Val string
}
func maleSleep(male *Male) {
defer w.Done()
male.Lock()
fmt.Println(male.Name + " sleeping...")
time.Sleep(5 * time.Second)
fmt.Println(male.Name + " wake up.")
male.Unlock()
}
var (
w sync.WaitGroup
)
func main() {
u := User{
Name: "Tom",
Age: 23,
}
m := Male{
User: u,
Val: "test",
}
w.Add(2)
go maleSleep(&m)
go maleSleep(&m)
w.Wait()
}
Go 的 Mutex 和 atomic
在 Go 中可以利用加锁的方式来保证并发安全,如下代码:
我们的目标是输出 sum = 200000,但是结果并不理想。因为
sum
是全局变量,会被两个 goroutine 操作,在操作的过程中可能会出现一个 goroutine 覆盖另一个 goroutine 值的情况出现。我们下边可以利用两种方法来解决:
sync.mutex 加锁
我们在对
sum
进行操作的时候加锁,防止出现并发安全问题atomic
我们使用 atomic 包对
sum
进行安全的并发操作mutex in struct
如下代码:
输出:
可以看到两个 goroutine 是串行执行的,这是因为一个 goroutine 获得了锁开始做事情,另外一个阻塞等待获得锁
嵌套结构体
在上述我们声明了一个嵌套结构体
Male
, 使用如上所示。关于嵌套结构体可以用下述方法初始化:
简单点的:
丑一点的: