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并发编程
发布评论