package main
import (
	"log"
	"math/rand"
	"sync"
	"time"
)
func main() {
	rand.Seed(time.Now().UnixNano())
	const N = 5
	var values [N]int32
	var wg sync.WaitGroup
	wg.Add(N)
	for i := 0; i < N; i++ {
		i := i
		go func() {
			values[i] = 50 + rand.Int31n(50)
			log.Println("Done:", i)
			wg.Done() // <=> wg.Add(-1)
		}()
	}
	wg.Wait()
	// All elements are guaranteed to be
	// initialized now.
	log.Println("values:", values)
}package main
import (
	"log"
	"sync"
)
func main() {
	log.SetFlags(0)
	x := 0
	doSomething := func() {
		x++
		log.Println("Hello")
	}
	var wg sync.WaitGroup
	var once sync.Once
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			once.Do(doSomething)
			log.Println("world!")
		}()
	}
	wg.Wait()
	log.Println("x =", x) // x = 1
}Both of the *sync.Mutex and *sync.RWMutex types implement the sync.Locker interface. So they both have two methods, Lock and Unlock, to prevent multiple data users from using a piece of data concurrently.
A Mutex value is often called a mutual exclusion lock. A zero Mutex value is an unlocked mutex. A Mutex value can only be locked when it is in unlocked status. In other words, once an addressable Mutex value m is locked successfully (a.k.a., a m.Lock() method call returns), a new attempt by a goroutine to lock the Mutex value will make the goroutine enter blocking state, until the Mutex value is unlocked (through a later m.Unlock() call).
Please note that m.Lock() and m.Unlock() are shorthands of (&m).Lock() and (&m).Unlock(), respectively.
package main
import (
	"fmt"
	"runtime"
	"sync"
)
type Counter struct {
	m sync.Mutex
	n uint64
}
func (c *Counter) Value() uint64 {
	c.m.Lock()
	defer c.m.Unlock()
	return c.n
}
func (c *Counter) Increase(delta uint64) {
	c.m.Lock()
	c.n += delta
	c.m.Unlock()
}
func main() {
	var c Counter
	for i := 0; i < 100; i++ {
		go func() {
			for k := 0; k < 100; k++ {
				c.Increase(1)
			}
		}()
	}
	// The loop is just for demo purpose.
	for c.Value() < 10000 {
		runtime.Gosched()
	}
	fmt.Println(c.Value()) // 10000
}RWMutex 的存在主要是对读优化,我们这样定义:
- 写锁定(
lock),对读写操作进行锁定 - 写解锁(
Unlock),对写锁定进行解锁 - 读锁定(
RLock),对读操作进行锁定 - 读解锁(
RUnlock),对读锁定进行解锁 
对于一个RWMutex值m,遵循规则:
- 同时只有一个 goroutine 能够获得写锁定,当一个 goroutine 获得写锁定之后,其他无论是读锁定还是写锁定都将阻塞直到写锁定解锁
 - 同时可以有任意多个 goroutine 获得读锁定,当一个 goroutine 获得读锁定之后,其他 goroutine 也能获得读锁定,但是写锁定将等待所有读锁定解锁之后才能够获取写锁定
 - 不能同时获得写锁定和读锁定(读和写互斥)
 - 假设 
m的读锁定已经被获取,在队列中已经有写锁定被阻塞,如果这时候有其他 goroutine 需要读锁定,为了避免循环读锁定,这个 goroutine 将被阻塞,m的读锁定被释放后,队列中那个需要写锁定的 goroutine 将被执行 - 假设 
m的写锁定已经被获取,在队列中已经有读锁定被阻塞,如果这时候有其他 goroutine 需要写锁定,为了避免循环写锁定,这个 goroutine 将被阻塞,m的写锁定被释放后,队列中那个需要读锁定的 goroutine 将被执行 
package main
import (
	"fmt"
	"runtime"
	"sync"
)
type Counter struct {
	m nc.RWMutex
	n uint64
}
func (c *Counter) Value() uint64 {
	c.m.RLock()
	defer c.m.RUnlock()
	return c.n
}
func (c *Counter) Increase(delta uint64) {
	c.m.Lock()
	c.n += delta
	c.m.Unlock()
}
func main() {
	var c Counter
	for i := 0; i < 100; i++ {
		go func() {
			for k := 0; k < 100; k++ {
				c.Increase(1)
			}
		}()
	}
	// The loop is just for demo purpose.
	for c.Value() < 10000 {
		runtime.Gosched()
	}
	fmt.Println(c.Value()) // 10000
}package main
import (
	"fmt"
	"sync"
)
func main() {
	var m sync.Map
	//Store
	m.Store("name", "Joe")
	m.Store("gender", "Male")
	//LoadOrStore
	//若key不存在,则存入key和value,返回false和输入的value
	v, ok := m.LoadOrStore("name1", "Jim")
	fmt.Println(ok, v) //false Jim
	//若key已存在,则返回true和key对应的value,不会修改原来的value
	v, ok = m.LoadOrStore("name", "aaa")
	fmt.Println(ok, v) //true Joe
	//Load
	v, ok = m.Load("name")
	if ok {
		fmt.Println("key存在,值是: ", v)
	} else {
		fmt.Println("key不存在")
	}
	//Range
	//遍历sync.Map
	f := func(k, v interface{}) bool {
		fmt.Println(k, v)
		return true
	}
	m.Range(f)
	//Delete
	m.Delete("name1")
	fmt.Println(m.Load("name1"))
}