sync

WaitGroup

如下例子,将不会输出任何东西。因为main goroutine立即退出,因此两个goroutine都没有来得及执行。

package main

import (
    "fmt"
)

func main() {
    go func() {
        fmt.Println(1)
    }()

    go func() {
        fmt.Println(2)
    }()
}

为了得到两个goroutine输出,可以在main中通过time.Sleep来延迟程序结束:

package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        fmt.Println(1)
    }()

    go func() {
        fmt.Println(2)
    }()

    time.Sleep(2 * time.Second)
}

也可以通过channel的方式:

package main

import (
    "fmt"
)

func main() {
    c := make(chan struct{})

    go func() {
        fmt.Println(1)
        c <- struct{}{}
    }()

    go func() {
        fmt.Println(2)
        c <- struct{}{}
    }()

    for i := 0; i < 2; i++ {
        <-c
    }
}

不过,更方便的是通过sync.WaitGroup来实现:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        fmt.Println(1)
        wg.Done()
    }()

    go func() {
        fmt.Println(2)
        wg.Done()
    }()

    wg.Wait()
}

WaitGroup可以等待一系列goroutine的执行完成。在main goroutine中通过Add方法指定等待的个数,在每个goroutine中调用Done方法标记该goroutine执行完成。Wait方法会等待,直到所有的goroutine执行结束。

Locker

Locker是一个接口,有LockUnlock方法:

type Locker interface {
    Lock()
    Unlock()
}

Mutex

Mutex提供了互斥锁的机制。例如:

var mutex sync.Mutex
mutex.Lock()
// ...
mutex.Unlock()

也可以通过defer的写法,例如:

var mutex sync.Mutex

func fn() {
    mutex.Lock()
    defer mutex.Unlock()

    // ...
}

RWMutex

RWMutex同时提供了共享锁和互斥锁的机制。其LockUnlock依然是互斥锁的操作,另外RLockRUnlock是共享锁。通过其Locker方法可以获取锁对象。