锁
# Go中的锁
# 互斥锁
获取到互斥锁的任务,阻塞其他任务来获取锁
意味着同一时间只能有一个任务才能持有互斥锁
package main
import (
"log"
"sync"
"time"
)
// HcMutex 是一个互斥锁
var HcMutex sync.Mutex
func runMutex(id int) {
log.Printf("[任务id:%d][尝试获取锁]", id)
HcMutex.Lock()
log.Printf("[任务id:%d][获取到了锁]", id)
time.Sleep(20 * time.Second) // 睡眠10秒钟
HcMutex.Unlock()
log.Printf("[任务id:%d][干完活了,释放锁]", id)
}
func runHcLock() {
go runMutex(1)
go runMutex(2)
go runMutex(3)
}
func main() {
runHcLock()
time.Sleep(6 * time.Minute)
/*
2021/09/02 22:15:46 [任务id:3][尝试获取锁]
2021/09/02 22:15:46 [任务id:3][获取到了锁]
2021/09/02 22:15:46 [任务id:1][尝试获取锁]
2021/09/02 22:15:46 [任务id:2][尝试获取锁]
2021/09/02 22:15:56 [任务id:1][获取到了锁]
2021/09/02 22:15:56 [任务id:3][干完活了,释放锁]
2021/09/02 22:16:06 [任务id:1][干完活了,释放锁]
2021/09/02 22:16:06 [任务id:2][获取到了锁]
2021/09/02 22:16:16 [任务id:2][干完活了,释放锁]
*/
}
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
44
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
44
# 读写锁
package main
import (
"log"
"sync"
"time"
)
// rwMutex 是一个读写锁
var rwMutex sync.RWMutex
func runReadLock(id int) {
log.Printf("[读任务id:%d][进入读方法,尝试获取锁]", id)
rwMutex.RLock() // 读锁
log.Printf("[读任务id:%d][获取到了读锁][开始干活,睡眠10秒]", id)
time.Sleep(10 * time.Second) // 睡眠10秒钟
rwMutex.RUnlock()
log.Printf("[读任务id:%d][完成读任务,释放读锁]", id)
}
func runWriteLock(id int) {
log.Printf("[写任务id:%d][进入写方法,尝试获取锁]", id)
rwMutex.Lock() // 写锁
log.Printf("[写任务id:%d][获取到了写锁][开始干活,睡眠10秒]", id)
time.Sleep(10 * time.Second) // 睡眠10秒钟
rwMutex.Unlock()
log.Printf("[写任务id:%d][完成写任务,释放写锁]", id)
}
// 全是写任务
func allWriteWorks() {
for i := 1; i <= 5; i++ {
go runWriteLock(i)
}
}
// 全是读任务
func allReadWorks() {
for i := 1; i <= 5; i++ {
go runReadLock(i)
}
}
// 先启动写任务
func writeFirst() {
go runWriteLock(1)
time.Sleep(1 * time.Second)
go runReadLock(1)
go runReadLock(2)
go runReadLock(3)
go runReadLock(4)
go runReadLock(5)
}
// 先启动写任务
func readFirst() {
go runReadLock(1)
go runReadLock(2)
go runReadLock(3)
go runReadLock(4)
go runReadLock(5)
time.Sleep(1 * time.Second)
go runWriteLock(1)
}
func main() {
log.Printf("执行读写锁效果的函数")
// 1. 同时多个写锁任务 => 如果并发使用读写锁的写锁时,退化成了互斥锁
//allWriteWorks()
/*
2021/09/02 22:27:28 执行读写锁效果的函数
2021/09/02 22:27:28 [写任务id:5][进入写方法,尝试获取锁]
2021/09/02 22:27:28 [写任务id:5][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:27:28 [写任务id:1][进入写方法,尝试获取锁]
2021/09/02 22:27:28 [写任务id:2][进入写方法,尝试获取锁]
2021/09/02 22:27:28 [写任务id:3][进入写方法,尝试获取锁]
2021/09/02 22:27:28 [写任务id:4][进入写方法,尝试获取锁]
2021/09/02 22:27:38 [写任务id:1][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:27:38 [写任务id:5][完成写任务,释放写锁]
2021/09/02 22:27:48 [写任务id:1][完成写任务,释放写锁]
2021/09/02 22:27:48 [写任务id:2][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:27:58 [写任务id:2][完成写任务,释放写锁]
2021/09/02 22:27:58 [写任务id:3][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:28:08 [写任务id:3][完成写任务,释放写锁]
2021/09/02 22:28:08 [写任务id:4][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:28:18 [写任务id:4][完成写任务,释放写锁]
*/
// 2. 同时多个读锁任务,使用读锁,可以同时加多把锁
//allReadWorks()
/*
2021/09/02 22:29:16 执行读写锁效果的函数
2021/09/02 22:29:16 [读任务id:5][进入读方法,尝试获取锁]
2021/09/02 22:29:16 [读任务id:2][进入读方法,尝试获取锁]
2021/09/02 22:29:16 [读任务id:4][进入读方法,尝试获取锁]
2021/09/02 22:29:16 [读任务id:2][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:29:16 [读任务id:4][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:29:16 [读任务id:5][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:29:16 [读任务id:1][进入读方法,尝试获取锁]
2021/09/02 22:29:16 [读任务id:1][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:29:16 [读任务id:3][进入读方法,尝试获取锁]
2021/09/02 22:29:16 [读任务id:3][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:29:26 [读任务id:3][完成读任务,释放读锁]
2021/09/02 22:29:26 [读任务id:4][完成读任务,释放读锁]
2021/09/02 22:29:26 [读任务id:2][完成读任务,释放读锁]
2021/09/02 22:29:26 [读任务id:5][完成读任务,释放读锁]
2021/09/02 22:29:26 [读任务id:1][完成读任务,释放读锁]
*/
// 3. 先启动写锁,后并发5个读锁任务
// 当有写锁存在时,读锁是施加不了的。写锁释放完,写锁可以并发的施加多个
// 写锁阻塞所有读锁
//writeFirst()
/*
2021/09/02 22:31:53 执行读写锁效果的函数
2021/09/02 22:31:53 [写任务id:1][进入写方法,尝试获取锁]
2021/09/02 22:31:53 [写任务id:1][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:31:54 [读任务id:2][进入读方法,尝试获取锁]
2021/09/02 22:31:54 [读任务id:5][进入读方法,尝试获取锁]
2021/09/02 22:31:54 [读任务id:4][进入读方法,尝试获取锁]
2021/09/02 22:31:54 [读任务id:1][进入读方法,尝试获取锁]
2021/09/02 22:31:54 [读任务id:3][进入读方法,尝试获取锁]
2021/09/02 22:32:03 [读任务id:5][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:32:03 [读任务id:3][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:32:03 [写任务id:1][完成写任务,释放写锁]
2021/09/02 22:32:03 [读任务id:2][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:32:03 [读任务id:4][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:32:03 [读任务id:1][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:32:13 [读任务id:1][完成读任务,释放读锁]
2021/09/02 22:32:13 [读任务id:2][完成读任务,释放读锁]
2021/09/02 22:32:13 [读任务id:4][完成读任务,释放读锁]
2021/09/02 22:32:13 [读任务id:5][完成读任务,释放读锁]
2021/09/02 22:32:13 [读任务id:3][完成读任务,释放读锁]
*/
// 4. 先启动读锁,先并发5个读锁任务,后启动一个写锁任务
// 当有读锁时,阻塞写锁
readFirst()
/*
2021/09/02 22:34:19 执行读写锁效果的函数
2021/09/02 22:34:19 [读任务id:5][进入读方法,尝试获取锁]
2021/09/02 22:34:19 [读任务id:5][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:34:19 [读任务id:3][进入读方法,尝试获取锁]
2021/09/02 22:34:19 [读任务id:2][进入读方法,尝试获取锁]
2021/09/02 22:34:19 [读任务id:2][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:34:19 [读任务id:3][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:34:19 [读任务id:4][进入读方法,尝试获取锁]
2021/09/02 22:34:19 [读任务id:4][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:34:19 [读任务id:1][进入读方法,尝试获取锁]
2021/09/02 22:34:19 [读任务id:1][获取到了读锁][开始干活,睡眠10秒]
2021/09/02 22:34:20 [写任务id:1][进入写方法,尝试获取锁]
2021/09/02 22:34:29 [读任务id:3][完成读任务,释放读锁]
2021/09/02 22:34:29 [读任务id:1][完成读任务,释放读锁]
2021/09/02 22:34:29 [读任务id:4][完成读任务,释放读锁]
2021/09/02 22:34:29 [读任务id:2][完成读任务,释放读锁]
2021/09/02 22:34:29 [读任务id:5][完成读任务,释放读锁]
2021/09/02 22:34:29 [写任务id:1][获取到了写锁][开始干活,睡眠10秒]
2021/09/02 22:34:39 [写任务id:1][完成写任务,释放写锁]
*/
time.Sleep(1 * time.Hour)
}
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
结论
- 同时多个写锁任务 -> 如果并发使用读写锁的写锁时,退化成了互斥锁
- 同时多个读锁任务,使用读锁,可以同时加多把锁
- 当有写锁存在时,读锁是施加不了的。写锁释放完,写锁可以并发的施加多个
- 先启动读锁,先并发5个读锁任务,后启动一个写锁任务,当有读锁时,阻塞写锁
编辑 (opens new window)
上次更新: 2021/10/21, 20:43:49