当前位置: 首页 > article >正文

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
	}
}


http://www.kler.cn/a/537207.html

相关文章:

  • 2、k8s的cni网络插件和基本操作命令
  • CSS outline详解:轮廓属性的详细介绍
  • WPF模板
  • 4.PPT:日月潭景点介绍【18】
  • HIVE如何注册UDF函数
  • 一次奇怪的空指针问题分析:事务、死锁与隐式回滚
  • 数据库性能优化(sql优化)_统计信息_yxy
  • 深入理解Docker:为你的爬虫项目提供隔离环境
  • C#+halcon机器视觉九点标定算法
  • 利用 Python 爬虫获取按关键字搜索淘宝商品的完整指南
  • 初探DeepSeek
  • PbootCMS 修改跳转提示,修改笑脸时间
  • CEF132 编译指南 Windows 篇 - 安装 Git 和 Python (三)
  • 【前端】Svelte的Writeable Store使用
  • 1.攻防世界 baby_web
  • 第三个Qt开发实例:利用之前已经开发好的LED驱动在Qt生成的界面中控制LED2的亮和灭
  • 【redis】数据类型之string
  • 一条sql 在MySQL中是如何执行的
  • c语言:取绝对值
  • [笔记] 汇编杂记(持续更新)
  • HTML学习笔记(6)
  • ubuntu中如何在vscode的终端目录后显示(当前的git分支名) 实测有用
  • 组合总和II(力扣40)
  • centos7-mini-2009下载docker
  • Cloudflare 2024 网络流量回顾:洞悉网络发展趋势与安全挑战
  • 数据库读写分离、事务的特性、事务隔离级别及默认级别、脏读不可重复读和幻读、更新丢失问题、写偏斜问题、MVCC