golang并发编程

编程入门 行业动态 更新时间:2024-10-09 11:22:08

<a href=https://www.elefans.com/category/jswz/34/1769831.html style=golang并发编程"/>

golang并发编程

文章目录

  • 1. 互斥锁
    • 1.1. 结构体 Mutex
      • 1.1.1 结构体定义
      • 1.1.2 结构体下方法
    • 1.2 Lock()/Unlock()方法
      • 1.2.1 语法
      • 2.2.2 示例(赤壁之战——锁的争夺)
  • 2. 读写锁
    • 2.1 结构体 RWMutex
    • 2.2 示例(献帝驾到——读锁间不互斥)
    • 2.3 示例(衣带诏——读写锁是互斥的)
    • 2.4 示例3(三顾茅庐——读锁是可重入锁)

1. 互斥锁

1.1. 结构体 Mutex

1.1.1 结构体定义

type Mutex struct {state int32sema  uint32
}

1.1.2 结构体下方法

  • Lock()
  • lockSlow()
  • Unlock()
  • unlockSlow(new int32)

1.2 Lock()/Unlock()方法

1.2.1 语法

  • 获取锁
func (m *Mutex) Lock()
  • 释放锁
func (m *Mutex) Unlock()
  • 示例
import ("sync"
)func main() {var mutex sync.Mutexfunc() {mutex.Lock()defer mutex.Unlock()}()
}

2.2.2 示例(赤壁之战——锁的争夺)

说明:魏蜀吴三个协程争夺锁,一个退出后,另一个才能获得锁。

func main() {var mutex sync.Mutexfmt.Println("======长江天险构造完成=======")for _,i := range []string{"刘备","曹操","孙权"} {go func(i string) {fmt.Printf("【%s】 出兵 \n", i)mutex.Lock()defer mutex.Unlock()fmt.Printf("【%s】 +++++占据长江+++++ \n", i)time.Sleep(3*time.Second)fmt.Printf("【%s】 退出长江 ====》 \n", i)}(i)}time.Sleep(10*time.Second)fmt.Println("=====END 折戟沉沙=====")
}

结果输出

======长江天险构造完成=======
【孙权】 出兵 
【孙权】 +++++占据长江+++++ 
【刘备】 出兵 
【曹操】 出兵 
【孙权】 退出长江 ====》 
【刘备】 +++++占据长江+++++ 
【刘备】 退出长江 ====》 
【曹操】 +++++占据长江+++++ 
【曹操】 退出长江 ====》 
=====END 折戟沉沙=====

2. 读写锁

特点

  • 许任意个读操作同时进行
  • 同一时刻,只允许有一个写操作

2.1 结构体 RWMutex

结构体

type RWMutex struct {w           MutexwriterSem   uint32readerSem   uint32readerCount int32readerWait  int32
}

该结构体方法

  • RLock()
  • RUnlock()
  • rUnlockSlow(r int32)
  • Lock()
  • Unlock()
  • RLocker() sync.Locker

2.2 示例(献帝驾到——读锁间不互斥)

如下,三个协程使用读锁同时进行。

func main() {var rwLock sync.RWMutexvar wg sync.WaitGroupwg.Add(3)fmt.Println("====== 献帝驾到 =======")for _,i := range []string{"刘备","曹操","孙权"} {go func(i string) {rwLock.RLock()defer rwLock.RUnlock()fmt.Printf("【%s】 觐见 +++++ \n", i)time.Sleep(3*time.Second)fmt.Printf("【%s】 退出 ====》\n", i)wg.Done()}(i)}wg.Wait()fmt.Println("=====END=====")
}

结果

====== 献帝驾到 =======
【孙权】 觐见 +++++ 
【刘备】 觐见 +++++ 
【曹操】 觐见 +++++ 
【曹操】 退出 ====》
【孙权】 退出 ====》
【刘备】 退出 ====》
===== END =====

2.3 示例(衣带诏——读写锁是互斥的)

读锁和写锁是互斥的

  • 读锁锁定后,写锁的线程等待。
  • 写锁锁定后,其他写锁和读锁线程都等待。

示例

献帝密诏董承,传衣带诏。其他人不能在此时觐见。
(其他人除了曹操我都是瞎写的)

func main() {var rwLock sync.RWMutexvar wg sync.WaitGroupwg.Add(5)fmt.Println("====== 献帝驾到 =======")go func() {rwLock.Lock()defer rwLock.Unlock()fmt.Println("【董承】 被密诏 !!!!")time.Sleep(3*time.Second)fmt.Println("【董承】 退出 ====》")wg.Done()}()for _,i := range []string{"曹操","孙权","袁绍","马腾"} {go func(i string) {rwLock.RLock()defer rwLock.RUnlock()fmt.Printf("【%s】 觐见 +++++ \n", i)time.Sleep(3*time.Second)fmt.Printf("【%s】 退出 ====》\n", i)wg.Done()}(i)}wg.Wait()fmt.Println("=====END=====")
}

结果(因为每个人是一个协程,所以每次打印结果顺序不同)

====== 献帝驾到 =======
【马腾】 觐见 +++++ 
【马腾】 退出 ====》
【董承】 被密诏 !!!!
【董承】 退出 ====》
【袁绍】 觐见 +++++ 
【曹操】 觐见 +++++ 
【孙权】 觐见 +++++ 
【曹操】 退出 ====》
【孙权】 退出 ====》
【袁绍】 退出 ====》
=====END=====

如上:

  • 马腾先到,觐见是读锁。
  • 董承第二个到,密诏是写锁,董承等待读锁解锁后进入。
  • 之后,曹操、孙权、袁绍依次到达,觐见是读锁,不会互斥,一起进入。

2.4 示例3(三顾茅庐——读锁是可重入锁)

一个协程可多次获取读锁(在该读锁解锁前)

  • 示例

刘备可以多次面见诸葛亮,获得诸葛亮的读锁,而不必先解锁。

func main() {var rwLock sync.RWMutexvar wg sync.WaitGroupwg.Add(3)fmt.Println("====== 三顾茅庐 =======")go func() {for i:=1;i<=3;i++{rwLock.RLock()fmt.Printf("【刘备】第 %d 次拜访【诸葛亮】 \n", i)time.Sleep(time.Second)}for j:=1;j<=3;j++{rwLock.RUnlock()wg.Done()}}()wg.Wait()fmt.Println("=====END=====")
}

结果:

====== 三顾茅庐 =======
【刘备】第 1 次拜访【诸葛亮】 
【刘备】第 2 次拜访【诸葛亮】 
【刘备】第 3 次拜访【诸葛亮】 
=====END=====

更多推荐

golang并发编程

本文发布于:2024-02-27 15:37:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1707160.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:golang

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!