mirror of
https://github.com/Estom/notes.git
synced 2026-02-09 21:36:58 +08:00
110 lines
2.3 KiB
Go
110 lines
2.3 KiB
Go
// sync 主要提供原子操作、互斥锁、读写锁
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
|
|
//
|
|
// Mutex
|
|
//
|
|
m := new(sync.Mutex)
|
|
c1, c2 := 0, 0
|
|
ch := make(chan int, 200)
|
|
for i := 0; i < 100; i++ {
|
|
go click(&c1, ch)
|
|
}
|
|
for i := 0; i < 100; i++ {
|
|
go clickWithMutex(&c2, m, ch)
|
|
}
|
|
for i := 0; i < 200; i++ { // 循环阻塞等待两百次任务完成
|
|
<-ch
|
|
}
|
|
fmt.Printf("c1: %d c2:%d\n", c1, c2) // c1: 56108 c2:10000 // 在多个 goroutine 中对同一变量进行操作时,一定要加锁
|
|
|
|
// RWMutex 读写锁
|
|
c3 := 0
|
|
rwLocker := new(sync.RWMutex)
|
|
clickWithRWMutex(&c3, rwLocker, ch)
|
|
fmt.Printf("c3: %d\n", c3)
|
|
|
|
//
|
|
// Once
|
|
//
|
|
once := new(sync.Once) // 保证 func 只会执行一次
|
|
for i := 0; i < 3; i++ {
|
|
go func(i int) {
|
|
once.Do(func() {
|
|
fmt.Println("once done: ", i)
|
|
})
|
|
fmt.Println("i: ", i)
|
|
ch <- 1
|
|
}(i)
|
|
}
|
|
for i := 0; i < 3; i++ {
|
|
<-ch
|
|
}
|
|
|
|
//
|
|
// WaitGroup
|
|
//
|
|
wg := new(sync.WaitGroup)
|
|
for i := 0; i < 3; i++ {
|
|
wg.Add(1) // 添加指定个元素到 WaitGroup 中
|
|
go Process(wg, i)
|
|
}
|
|
wg.Wait() // 阻塞直到 WaitGroup 中所有任务完成
|
|
|
|
//
|
|
// 原子操作
|
|
//
|
|
var u1 uint32
|
|
atomic.AddUint32(&u1, 2) // 原子操作只针对长度固定的数据
|
|
fmt.Println(u1) // 2
|
|
fmt.Println(atomic.SwapUint32(&u1, 100)) // 2 // 返回旧数据
|
|
fmt.Println(u1) // 100
|
|
fmt.Println(atomic.LoadUint32(&u1)) // 互斥读:在读取期间,程序的其他部分无法再对变量进行读写操作
|
|
}
|
|
|
|
func clickWithRWMutex(total *int, rwLocker *sync.RWMutex, ch chan int) {
|
|
for i := 0; i < 1000; i++ {
|
|
rwLocker.Lock()
|
|
*total++
|
|
rwLocker.Unlock()
|
|
if i == 500 {
|
|
rwLocker.RLock()
|
|
fmt.Println(*total) // 501 // 只保证读,不保证写...惊不惊喜意不意外
|
|
rwLocker.RUnlock()
|
|
}
|
|
}
|
|
ch <- 1
|
|
}
|
|
|
|
func click(total *int, ch chan int) {
|
|
for i := 0; i < 1000; i++ {
|
|
*total += 1
|
|
}
|
|
ch <- 1
|
|
}
|
|
|
|
func clickWithMutex(total *int, m *sync.Mutex, ch chan int) {
|
|
for i := 0; i < 1000; i++ {
|
|
m.Lock()
|
|
*total += 1
|
|
m.Unlock()
|
|
}
|
|
ch <- 1
|
|
}
|
|
|
|
// 这里必须传入指针,对 wg 变量进行修改
|
|
func Process(wg *sync.WaitGroup, id int) {
|
|
time.Sleep(1 * time.Second)
|
|
fmt.Printf("task %d is done\n", id)
|
|
wg.Done()
|
|
}
|