1.使用互斥锁mutex
定义一个struct,结构体中含有可计数的变量,并嵌入sync.Mutex,使对象具有加锁和解锁的能力,每次对对象进行加操作的时候先进行加锁,计算结束后再进行解锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
type SafeCounter struct {
v map[string]int
mutex sync.Mutex
}
func (c *SafeCounter)Inc(key string){
c.mutex.Lock()
c.v[key]++
c.mutex.Unlock()
wg.Done()
}
func(c *SafeCounter)Value(key string) int{
c.mutex.Lock()
defer c.mutex.Unlock()
return c.v[key]
}
func main() {
counter := SafeCounter{
v: make(map[string]int),
}
for i:=0;i<999999;i++{
wg.Add(1)
go counter.Inc("mykey")
}
wg.Wait()
fmt.Println(counter.Value("mykey"))
}
|
2.使用 atomic 包,执行原子操作
使用atomic包,可以对int进行原子操作,其背后使用的是汇编语言实现的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package main
import (
"fmt"
"sync"
"sync/atomic"
)
var wg sync.WaitGroup
var SafeCounter int64
func Inc() {
atomic.AddInt64(&SafeCounter, 1)
wg.Done()
}
func Value() int64 {
return SafeCounter
}
func main() {
for i := 0; i < 999999; i++ {
wg.Add(1)
go Inc()
}
wg.Wait()
fmt.Println(Value())
}
|
3.使用CSP模型
创建一个长度为1的channel,用单个goroutine循环等待常驻监听channel传过来的值,并进行消费。通过channel保证了对全局变量的单线程操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
var SafeCounter int64
func Inc(c chan int64) {
//常驻监听
for{
select {
case v:= <-c:
SafeCounter += v
}
}
}
func Value() int64 {
return SafeCounter
}
func main() {
c := make(chan int64)
go Inc(c)
for i := 0; i < 999999; i++ {
wg.Add(1)
go func() {
c <-1
wg.Done()
}()
}
wg.Wait()
fmt.Println(Value())
}
|