1、Golang的锁
sync.Mutexsync.RWMutex
  RLock()叫读锁。它不是绝对锁,可以有多个读者同时获取此锁
  Lock()叫写锁,它是个绝对锁,一旦某人拿了这个锁,别人就不能再获取此锁了。
2、sync.WaitGroup

https://blog.csdn.net/u013474436/article/details/88749749
经常会看到如下代码

func main(){
	for i := 0; i < 100; i++ {
		go fmt.Println(i)
	}
	time.Sleep(time.Second)
}
time.Sleep()time.Sleep()
time.Sleep()

可以考虑使用管道来完成上述操作:

func main(){
	c := make(chan bool, 100)
	for i := 0; i < 100; i ++ {
		go func(num int){
			fmt.Println(num)
			c <- true
		}(i)
	}
	
	for i := 0; i < 100; i++ {
		<- c
	}
}

首先可以肯定的是使用管道可以达到我们的目的,且不仅能达到,还能十分完美的达到目的

但是管道在这里显得有些大材小用了,因为它被设计出来不仅仅只是在这里用作同步处理,在这里使用管道实际上是不合适的。而且假设我们有一万、十万甚至更多的for循环,也要申请同样数量大小的管道出来,对内存也是不小的开销。

sync.WaitGroup
WaitGroupAdd(),Done(),Wait()Add(n)nDone()-1wait()0
WaitGroup
func main(){
	wg := sync.WaitGroup{}
	wg.Add(100)
	for i := 0; i < 100; i++{
		go func(num int){
			fmt.Println(i)
			wg.Done()
		}(i)
	}
}
100for1Wait()wg100forWaitGroup

注意事项

1.计数器不能设置为负值

Add()wg
panic: sync: negative WaitGroup counter

goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc042008230, 0xffffffffffffff9c)
    D:/Go/src/sync/waitgroup.go:75 +0x1d0
main.main()
    D:/code/go/src/test-src/2-Package/sync/waitgroup/main.go:10 +0x54

Done()

2.WaitGroup对象不是一个引用类型

func main(){
	wg := sync.WaitGroup{}
	wg.Add(100)
	for i := 0; i < 100; i ++ {
		go f(i, &wg)
	}
	wg.Wait()
}
// 一定要通过指针传值,不然进程会进入死锁状态
func f(i int, wg *sync.WaitGroup){
	fmt.Println(i)
	wg.Done()
}
3、sync.Mutex

Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,不能再次对其进行加锁,直到利用Unlock()解锁后才能再次加锁,适用于读写不确定的场景,即读写次数没有明显的区别,并且只允许一个读或者写的场景,所以该锁也叫全局锁

已经锁定的Mutex并不与特定的goroutine关联,这样可以利用一个goroutine加锁,再利用其它goroutine对其解锁

package main
 
import (
	"fmt"
	"runtime"
	"sync"
)
 
type Counter struct {
	mu sync.Mutex
	x  int64
}
 
func (c *Counter) Inc() {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.x++
}
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	c := Counter{}
	var wait sync.WaitGroup
	wait.Add(4)
	for k := 4; k > 0; k-- {
		go func() {
			for i := 2500000; i > 0; i-- {
				c.Inc()
			}
			wait.Done()
		}()
	}
	wait.Wait()
	fmt.Println(c.x)
}
4、sync.RWMutex

RWMutex是一个读写锁,该锁可以加多个读锁或者一个写锁,其经常用于读次数远远多于写次数的场景

  • func(rw *RWMutex) Lock() 写锁,如果在添加写锁之前已经有其他的读锁和写锁,则lock就会阻塞直到该锁可用,已阻塞的Lock调用会从获得的锁中排除新的读取器