出现临界资源访问问题的代码
package main
import (
"fmt"
"math/rand"
"time"
)
var ticket = 10
func main() {
go sellTicket("售票口1")
go sellTicket("售票口2")
go sellTicket("售票口3")
go sellTicket("售票口4")
time.Sleep(3*time.Second)
}
func sellTicket(name string) {
rand.Seed(time.Now().UnixNano())
for {
if ticket > 0 {
time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
fmt.Println(name, "售出", ticket)
ticket--
} else {
break
}
}
}
不要以共享内存的方式去通信,而是以通信的方式共享内存
- sync
- 鼓励使用channel
使用waitgroup实现同步(信号量)
WaitGroup 同步等待组
Add() 设置等待组中goroutine的数量
Wait() 让当前gouroutine处于阻塞状态
Done() 让等待组中计数器减一
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
wg.Add(2)
go fun1()
go fun2()
fmt.Println("main... 阻塞")
wg.Wait()
fmt.Println("main ... 完成")
}
func fun1() {
for i := 0; i < 5; i++ {
fmt.Println("func1 ", i)
}
wg.Done()
}
func fun2() {
defer wg.Done()
for i := 0; i < 5; i++ {
fmt.Println("func2 ", i)
}
}
当这段程序中wg.Add(2)
改为wg.Add(3)
的时候,就会因为计数器最终为1,main函数无法解除阻塞,产生死锁。
mutex解决一开始的临界资源访问问题
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var ticket = 10
var mutex sync.Mutex
func main() {
go sellTicket("售票口1")
go sellTicket("售票口2")
go sellTicket("售票口3")
go sellTicket("售票口4")
time.Sleep(5 * time.Second)
}
func sellTicket(name string) {
rand.Seed(time.Now().UnixNano())
for {
mutex.Lock()
if ticket > 0 {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
fmt.Println(name, "售出", ticket)
ticket--
} else {
mutex.Unlock()
fmt.Println("票卖完了...")
break
}
mutex.Unlock()
}
}
使用WaitGroup让main函数等待四个goroutine完成后再结束
(替代掉time.Sleep)
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var ticket = 10
var mutex sync.Mutex
var wg sync.WaitGroup
func main() {
wg.Add(4)
go sellTicket("售票口1")
go sellTicket("售票口2")
go sellTicket("售票口3")
go sellTicket("售票口4")
wg.Wait()
fmt.Println("程序结束了")
}
func sellTicket(name string) {
rand.Seed(time.Now().UnixNano())
defer wg.Done()
for {
mutex.Lock()
if ticket > 0 {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
fmt.Println(name, "售出", ticket)
ticket--
} else {
mutex.Unlock()
fmt.Println("票卖完了...")
break
}
mutex.Unlock()
}
}
网友评论