Skip to content

Commit da8d814

Browse files
author
xian-jie.shen
committed
feat(learning): 第40条 理解包内测试与包外测试的差别
1 parent f1f6e19 commit da8d814

14 files changed

+1510
-28
lines changed

chapter6/sources/go-channel-case-9.go

-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,4 @@ func main() {
3939
}
4040
}
4141
fmt.Println("program end")
42-
time.Sleep
4342
}

chapter6/sources/go-sync-package-1_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,56 @@ func BenchmarkCriticalSectionSyncByChan(b *testing.B) {
3232
criticalSectionSyncByChan()
3333
}
3434
}
35+
36+
var i int
37+
var j int
38+
var mut sync.Mutex
39+
var cha = make(chan struct{}, 1)
40+
41+
func CriticalSectionSyncByMutex2() {
42+
mut.Lock()
43+
defer mut.Unlock()
44+
_ = i
45+
}
46+
47+
func CriticalSectionSyncByChan2() {
48+
cha <- struct{}{}
49+
_ = j
50+
<-cha
51+
}
52+
53+
func CriticalSectionSyncWriteByMutex2() {
54+
mut.Lock()
55+
defer mut.Unlock()
56+
i++
57+
}
58+
59+
func CriticalSectionSyncWriteByChan2() {
60+
cha <- struct{}{}
61+
j++
62+
<-cha
63+
}
64+
65+
func BenchmarkCriticalSectionSyncWriteByMutex2(b *testing.B) {
66+
for i := 0; i < b.N; i++ {
67+
CriticalSectionSyncWriteByMutex2()
68+
}
69+
}
70+
71+
func BenchmarkCriticalSectionSyncWriteByChan2(b *testing.B) {
72+
for i := 0; i < b.N; i++ {
73+
CriticalSectionSyncWriteByChan2()
74+
}
75+
}
76+
77+
func BenchmarkCriticalSectionSyncByMutex2(b *testing.B) {
78+
for i := 0; i < b.N; i++ {
79+
CriticalSectionSyncByMutex2()
80+
}
81+
}
82+
83+
func BenchmarkCriticalSectionSyncByChan2(b *testing.B) {
84+
for i := 0; i < b.N; i++ {
85+
CriticalSectionSyncByChan2()
86+
}
87+
}

chapter6/sources/go-sync-package-2.go

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"fmt"
45
"log"
56
"sync"
67
"time"
@@ -11,7 +12,7 @@ type foo struct {
1112
sync.Mutex
1213
}
1314

14-
func main() {
15+
func CopySyncType() {
1516
f := foo{n: 17}
1617

1718
go func(f foo) {
@@ -44,3 +45,45 @@ func main() {
4445
f.Unlock()
4546
log.Println("g1: unlock foo ok")
4647
}
48+
49+
type clock struct {
50+
i int
51+
sync.Mutex
52+
}
53+
54+
func CopySyncType2() {
55+
s := clock{i: 1}
56+
57+
go func(c clock) {
58+
for {
59+
fmt.Println("g1 try lock...")
60+
c.Lock()
61+
fmt.Println("g1 lock")
62+
time.Sleep(3 * time.Second)
63+
c.Unlock()
64+
fmt.Println("g1 unlock")
65+
}
66+
}(s)
67+
68+
s.Lock()
69+
fmt.Println("g0 lock")
70+
go func(c clock) {
71+
for {
72+
fmt.Println("g2 try lock...")
73+
c.Lock()
74+
fmt.Println("g2 lock")
75+
time.Sleep(5 * time.Second)
76+
c.Unlock()
77+
fmt.Println("g2 unlock")
78+
}
79+
}(s)
80+
81+
time.Sleep(1000 * time.Second)
82+
s.Unlock()
83+
fmt.Println("g0 unlock")
84+
}
85+
86+
func main() {
87+
// CopySyncType()
88+
CopySyncType2()
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package main
2+
3+
import (
4+
"sync"
5+
"testing"
6+
)
7+
8+
var cs1 = 0 // 模拟临界区要保护的数据
9+
var mu1 sync.Mutex
10+
var cs2 = 0 // 模拟临界区要保护的数据
11+
var mu2 sync.RWMutex
12+
13+
func BenchmarkReadSyncByMutex(b *testing.B) {
14+
b.RunParallel(func(pb *testing.PB) {
15+
for pb.Next() {
16+
mu1.Lock()
17+
_ = cs1
18+
mu1.Unlock()
19+
}
20+
})
21+
}
22+
23+
func BenchmarkReadSyncByRWMutex(b *testing.B) {
24+
b.RunParallel(func(pb *testing.PB) {
25+
for pb.Next() {
26+
mu2.RLock()
27+
_ = cs2
28+
mu2.RUnlock()
29+
}
30+
})
31+
}
32+
33+
func BenchmarkWriteSyncByRWMutex(b *testing.B) {
34+
b.RunParallel(func(pb *testing.PB) {
35+
for pb.Next() {
36+
mu2.Lock()
37+
cs2++
38+
mu2.Unlock()
39+
}
40+
})
41+
}

chapter6/sources/go-sync-package-3_test.go

+53-23
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,67 @@ import (
55
"testing"
66
)
77

8-
var cs1 = 0 // 模拟临界区要保护的数据
9-
var mu1 sync.Mutex
10-
var cs2 = 0 // 模拟临界区要保护的数据
11-
var mu2 sync.RWMutex
12-
13-
func BenchmarkReadSyncByMutex(b *testing.B) {
14-
b.RunParallel(func(pb *testing.PB) {
15-
for pb.Next() {
16-
mu1.Lock()
17-
_ = cs1
18-
mu1.Unlock()
8+
var data1 int
9+
var mut1 sync.Mutex
10+
var data2 int
11+
var mut2 sync.RWMutex
12+
13+
func BenchmarkSyncReadByMutex(b *testing.B) {
14+
b.RunParallel(func(b *testing.PB) {
15+
for b.Next() {
16+
mut1.Lock()
17+
_ = data1
18+
mut1.Unlock()
19+
}
20+
})
21+
}
22+
23+
func BenchmarkSyncReadByRWMutexRLock(b *testing.B) {
24+
b.RunParallel(func(b *testing.PB) {
25+
for b.Next() {
26+
mut2.RLock()
27+
_ = data1
28+
mut2.RUnlock()
29+
}
30+
})
31+
}
32+
33+
func BenchmarkSyncReadByRWMutexLock(b *testing.B) {
34+
b.RunParallel(func(b *testing.PB) {
35+
for b.Next() {
36+
mut2.Lock()
37+
_ = data1
38+
mut2.Unlock()
39+
}
40+
})
41+
}
42+
43+
func BenchmarkSyncWriteByMutex(b *testing.B) {
44+
b.RunParallel(func(b *testing.PB) {
45+
for b.Next() {
46+
mut1.Lock()
47+
data1++
48+
mut1.Unlock()
1949
}
2050
})
2151
}
2252

23-
func BenchmarkReadSyncByRWMutex(b *testing.B) {
24-
b.RunParallel(func(pb *testing.PB) {
25-
for pb.Next() {
26-
mu2.RLock()
27-
_ = cs2
28-
mu2.RUnlock()
53+
func BenchmarkSyncWriteByRWMutexRLock(b *testing.B) {
54+
b.RunParallel(func(b *testing.PB) {
55+
for b.Next() {
56+
mut2.RLock()
57+
data1++
58+
mut2.RUnlock()
2959
}
3060
})
3161
}
3262

33-
func BenchmarkWriteSyncByRWMutex(b *testing.B) {
34-
b.RunParallel(func(pb *testing.PB) {
35-
for pb.Next() {
36-
mu2.Lock()
37-
cs2++
38-
mu2.Unlock()
63+
func BenchmarkSyncWriteByRWMutexLock(b *testing.B) {
64+
b.RunParallel(func(b *testing.PB) {
65+
for b.Next() {
66+
mut2.Lock()
67+
data1++
68+
mut2.Unlock()
3969
}
4070
})
4171
}

chapter6/sources/go-sync-package-4.go

+69-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func spawnGroup(f func(i int), num int, mu *sync.Mutex) <-chan signal {
4646
return c
4747
}
4848

49-
func main() {
49+
func showSyncPkg1() {
5050
fmt.Println("start a group of workers...")
5151
mu := &sync.Mutex{}
5252
c := spawnGroup(worker, 5, mu)
@@ -60,4 +60,72 @@ func main() {
6060

6161
<-c
6262
fmt.Println("the group of workers work done!")
63+
64+
}
65+
66+
func work(duration int) {
67+
fmt.Println("worker start")
68+
time.Sleep(time.Millisecond * time.Duration(duration))
69+
fmt.Println("worker end")
70+
}
71+
72+
var ready2 bool
73+
var mutex sync.Mutex
74+
75+
func spawnGoroutine(f func(i int), nums int, cond *sync.Cond) <-chan struct{} {
76+
done := make(chan struct{})
77+
var wg sync.WaitGroup
78+
for i := 0; i < nums; i++ {
79+
wg.Add(1)
80+
go func(i int) {
81+
defer wg.Done()
82+
cond.L.Lock()
83+
if !ready2 {
84+
cond.Wait()
85+
}
86+
cond.L.Unlock()
87+
f(i)
88+
// for {
89+
// mu.Lock()
90+
// if !ready2 {
91+
// mu.Unlock()
92+
// // fmt.Printf("goroutine-%d: not ready..", i)
93+
// time.Sleep(time.Second)
94+
// continue
95+
// }
96+
// mu.Unlock()
97+
// f(i)
98+
// return
99+
// }
100+
}(i)
101+
}
102+
103+
go func() {
104+
wg.Wait()
105+
done <- struct{}{}
106+
}()
107+
108+
return done
109+
}
110+
111+
func showSyncPkg2() {
112+
// mu := &sync.Mutex{}
113+
cond := sync.NewCond(&sync.Mutex{})
114+
c := spawnGoroutine(work, 5, cond)
115+
fmt.Println("exec group workers")
116+
time.Sleep(5 * time.Second)
117+
118+
cond.L.Lock()
119+
ready2 = true
120+
cond.Broadcast()
121+
fmt.Println("trigger worker")
122+
cond.L.Unlock()
123+
124+
<-c
125+
fmt.Println("all worker done")
126+
}
127+
128+
func main() {
129+
// showSyncPkg1()
130+
showSyncPkg2()
63131
}

chapter6/sources/go-sync-package-6.go

+47-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func GetInstance(id int) *Foo {
2828
return instance
2929
}
3030

31-
func main() {
31+
func showOnceDo() {
3232
var wg sync.WaitGroup
3333
for i := 0; i < 5; i++ {
3434
wg.Add(1)
@@ -45,3 +45,49 @@ func main() {
4545
wg.Wait()
4646
log.Printf("all goroutines exit\n")
4747
}
48+
49+
type inst struct {
50+
}
51+
52+
var ist *inst
53+
54+
// var instance *Foo
55+
var once2 sync.Once
56+
57+
func getInst(id int) *inst {
58+
log.Printf("goroutine-%d: enter getInst", id)
59+
defer func() {
60+
if p := recover(); p != nil {
61+
log.Println("caught a panic: ", p)
62+
}
63+
}()
64+
once2.Do(func() {
65+
ist = &inst{}
66+
log.Printf("goroutine-%d: getInst: %p\n", id, ist)
67+
panic("raise a panic")
68+
})
69+
return ist
70+
}
71+
72+
func showOnceDo2() {
73+
var wg sync.WaitGroup
74+
for i := 0; i < 5; i++ {
75+
wg.Add(1)
76+
go func(id int) {
77+
defer wg.Done()
78+
ist := getInst(id)
79+
log.Printf("goroutine-%d: instance: %+v %p\n", id, ist, ist)
80+
}(i + 1)
81+
}
82+
time.Sleep(5 * time.Second)
83+
ist := getInst(0)
84+
log.Printf("goroutine-%d: get instance: %p\n", 0, ist)
85+
86+
wg.Wait()
87+
log.Println("done")
88+
}
89+
90+
func main() {
91+
// showOnceDo()
92+
showOnceDo2()
93+
}

0 commit comments

Comments
 (0)