go的sync包学习
包含了sync.Mutex,sync.RWMutex,sync.Cond,sync.Map,sync.Once等demo
sync.Mutex
//讲解mutex
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Toilet struct {
m sync.Mutex
}
type Person struct {
Name string
}
var DateTime = "2006-01-02 15:04:05"
var otherThing = []string{"唱歌", "跳舞", "修仙"}
func main() {
t := &Toilet{}
wg := sync.WaitGroup{}
wg.Add(5)
for i := 0; i < 5; i++ {
go func(i int, t *Toilet, wg *sync.WaitGroup) {
p := Person{
Name: fmt.Sprintf("%d 号", i),
}
p.InToiletLock(t, wg)
}(i, t, &wg)
}
wg.Wait()
}
func (p *Person) InToiletLock(t *Toilet, wg *sync.WaitGroup) {
defer wg.Done()
t.m.Lock()
i := rand.Intn(5)
fmt.Printf("%s 上厕所时间 %v\n", p.Name, time.Now().Format(DateTime))
time.Sleep(time.Duration(i) * time.Second)
t.m.Unlock()
}
func (p *Person) InToiletUnLock(wg *sync.WaitGroup) {
defer wg.Done()
i := rand.Intn(5)
fmt.Printf("%s 上厕所时间 %v\n", p.Name, time.Now().Format(DateTime))
time.Sleep(time.Duration(i) * time.Second)
}
sync.RWMutex
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Cinema struct {
rw *sync.RWMutex
}
type Person struct {
Name string
}
type Admin struct {
Name string
}
func main() {
//example01()
exmples2()
}
func (p *Person) SitDown(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("%s 观众坐下!\n", p.Name)
}
func (p *Person) StartWatch() {
fmt.Printf("%s 开始观看!\n", p.Name)
i := time.Duration(rand.Intn(5) + 1)
time.Sleep(i * time.Second)
fmt.Printf("%s 观看结束!\n", p.Name)
}
func (p *Person) WatchMovie(c *Cinema, wg *sync.WaitGroup, b chan int) {
c.rw.RLock()
//先坐下
p.SitDown(wg)
<-b
//看电影
p.StartWatch()
c.rw.RUnlock()
}
func (a *Admin) ChangeMovie(c *Cinema, wg *sync.WaitGroup) {
defer wg.Done()
c.rw.Lock()
fmt.Printf("所有观众看完电影,%s管理员切换影片\n", a.Name)
c.rw.Unlock()
}
func example01() {
c := &Cinema{rw: &sync.RWMutex{}}
a := &Admin{Name: "超人"}
b := make(chan int)
wg := sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int, c *Cinema, wg *sync.WaitGroup, b chan int) {
p := Person{
Name: fmt.Sprintf("%d 号观众", i),
}
p.WatchMovie(c, wg, b)
}(i, c, &wg, b)
}
wg.Wait()
fmt.Printf("所有观众入座,开始播放电影\n")
close(b)
wg.Add(1)
go func(wg *sync.WaitGroup) {
a.ChangeMovie(c, wg)
}(&wg)
wg.Wait()
}
type Desk struct {
rw *sync.RWMutex
Snacks int
}
func (d *Desk) PlaceSnacks(wg *sync.WaitGroup) {
defer wg.Done()
d.rw.Lock()
d.Snacks = 10
time.Sleep(3 * time.Second)
fmt.Printf("零食准备完毕...\n")
d.rw.Unlock()
}
func (p *Person) GetSnacks(d *Desk, wg *sync.WaitGroup) {
for !d.rw.TryRLock() {
fmt.Printf("桌上没零食,%s 望眼欲穿\n", p.Name)
time.Sleep(2 * time.Second)
}
d.rw.RUnlock()
defer wg.Done()
defer d.rw.Unlock()
d.rw.Lock()
if d.Snacks > 0 {
fmt.Printf("%s 抢到零食,开心\n", p.Name)
d.Snacks--
return
}
fmt.Printf("%s 没抢到零食,难受\n", p.Name)
}
func exmples2() {
d := Desk{
rw: &sync.RWMutex{},
}
wg := sync.WaitGroup{}
wg.Add(12)
go d.PlaceSnacks(&wg)
for i := 0; i < 11; i++ {
p := Person{
Name: fmt.Sprintf("%d 号猿猴", i),
}
go p.GetSnacks(&d, &wg)
}
wg.Wait()
}
sync.Cond
package main
//sync.Cond进行学习
import (
"fmt"
"sync"
"time"
)
var start = false
var done = false
func main() {
wg := sync.WaitGroup{}
wg.Add(10)
m := &sync.Mutex{}
c := sync.NewCond(m)
for i := 0; i < 10; i++ {
go Soliders(i, c, &wg)
}
go Waiter(c)
Officer(c)
wg.Wait()
fmt.Println("所有大兵干完饭")
CleanUp(c)
time.Sleep(time.Second * 3)
fmt.Println("打扫结束")
}
func CleanUp(c *sync.Cond) {
c.L.Lock()
done = true
c.L.Unlock()
c.Signal()
}
func Officer(c *sync.Cond) {
fmt.Printf("长官准备中....\n")
time.Sleep(time.Second * 5)
c.L.Lock()
start = true
c.L.Unlock()
c.Broadcast()
}
func Soliders(i int, c *sync.Cond, wg *sync.WaitGroup) {
defer wg.Done()
c.L.Lock()
fmt.Printf("大兵%d号等待干饭...\n", i)
for !start {
c.Wait()
}
fmt.Printf("大兵%d号开始干饭...\n", i)
c.L.Unlock()
}
func Waiter(c *sync.Cond) {
c.L.Lock()
for !done {
c.Wait()
}
fmt.Println("用餐结束,开始打扫......")
c.L.Unlock()
return
}
sync.Map
func main() {
m := make(map[int]int)
for i := 0; i < 1000; i++ {
go func(m map[int]int) {
m[i] = i
}(m)
}
}
func TestStore(t *testing.T) {
var sum sync.Map
sum.Store("a", 1)
//sum.Delete("a")
val, ok := sum.Load("a")
fmt.Println(val, ok)
}
func TestLoadAndDelete(t *testing.T) {
var smm sync.Map
smm.Store("a", 1)
val, loaded := smm.LoadAndDelete("a")
fmt.Printf("value is %v,is exist %v \n", val, loaded)
_, ok := smm.LoadAndDelete("a")
fmt.Printf("value is ,is exist %v \n", ok)
}
func TestLoadAndStore(t *testing.T) {
var smm sync.Map
value, loaded := smm.LoadOrStore("a", 1)
fmt.Printf("value is %v,is exist %v \n", value, loaded)
value, loaded = smm.LoadOrStore("a", 2)
fmt.Printf("value is %v,is exist %v \n", value, loaded)
smm.Store("a", 3)
value, loaded = smm.Load("a")
fmt.Printf("value is %v,is exist %v \n", value, loaded)
}
func TestRange(t *testing.T) {
var smm sync.Map
for i := 0; i < 10; i++ {
go func(m *sync.Map, key int, value int) {
m.Store(key, value)
}(&smm, i, i)
}
time.Sleep(2 * time.Second)
smm.Range(func(key, value interface{}) bool {
fmt.Println(key, value)
return true
})
}
sync.pool
import (
"bytes"
"log"
"net/http"
"runtime"
"sync"
"time"
)
var pool = sync.Pool{New: func() interface{} { return new([]bytes.Buffer) }}
func main() {
var pool sync.Pool
for i := 0; i < 10; i++ {
pool.Put(&http.Client{
Timeout: time.Second * time.Duration(10),
})
}
runtime.GC()
runtime.GC()
p := pool.Get()
if p == nil {
log.Fatal("p is nil")
} else {
pool.Put(p)
}
}
sync.Once
package main
import (
"fmt"
"math/rand"
"sync"
"sync/atomic"
"testing"
"time"
)
//主要涉及sync.Once
type Config struct {
Server string
Port int64
}
var (
config *Config
once OncePower
initedConfig uint32
)
type OncePower struct {
sync.Mutex
done uint32
}
func init() {
rand.Seed(time.Now().UnixNano())
}
func (p *OncePower) Do(fun func() error) error {
if atomic.LoadUint32(&p.done) == 0 {
return p.doSlow(fun)
}
return nil
}
func (o *OncePower) doSlow(fun func() error) error {
o.Lock()
defer o.Unlock()
if o.done == 0 {
err := fun()
if err != nil {
return err
}
atomic.StoreUint32(&o.done, 1)
}
return nil
}
func initConfig() error {
//randInt := rand.Intn(6)
//if randInt > 2 {
// return errors.New("初始化失败了....")
//}
config = &Config{
Server: "127.0.0.1",
Port: 9999,
}
fmt.Println("init config....")
if atomic.LoadUint32(&initedConfig) == 0 {
atomic.StoreUint32(&initedConfig, 1)
}
return nil
}
func ReadConfig(i int) *Config {
fmt.Println("i >>>", i)
err := once.Do(initConfig)
fmt.Println("once err >>>", err)
return config
}
func TestSingleTon(t *testing.T) {
wait := sync.WaitGroup{}
for i := 0; i < 10; i++ {
wait.Add(1)
go func(i int) {
defer wait.Done()
_ = ReadConfig(i)
}(i)
}
wait.Wait()
}
func TestOnce(t *testing.T) {
var once sync.Once
onceBody := func() {
fmt.Println("only once")
}
done := make(chan bool)
for i := 0; i < 10; i++ {
go func() {
once.Do(onceBody)
done <- true
fmt.Println("true done", i)
}()
}
for i := 0; i < 10; i++ {
<-done
}
}