go的sync包学习

包含了sync.Mutex,sync.RWMutex,sync.Cond,sync.Map,sync.Once等demo

sync.Mutex

go 复制代码
//讲解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

go 复制代码
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

go 复制代码
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

go 复制代码
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

go 复制代码
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

go 复制代码
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
	}
}
相关推荐
Scott9999HH3 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社4 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海4 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖5 小时前
JDK 26 新特性详解
java·开发语言
马优晨5 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117767 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao7 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
人邮异步社区7 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大8 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai8 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang