Skip to content

Commit 1bc7f6a

Browse files
committed
update lesson23
1 parent 79a7b92 commit 1bc7f6a

File tree

3 files changed

+196
-7
lines changed

3 files changed

+196
-7
lines changed

workspace/lesson19/goroutine7.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ func main() {
1818
/* wg跟踪10个goroutine */
1919
size := 10
2020
wg.Add(size)
21-
/* 开启10个goroutine并发执行 */
21+
/* 开启10个goroutine并发执行
22+
这里10个goroutine在闭包里都用了变量i,等闭包真正执行的时候,i的值
23+
已经改变,所以这种实现方式不安全
24+
*/
2225
for i:=0; i<size; i++ {
2326
go func() {
2427
defer wg.Done()

workspace/lesson23/readme.md

Lines changed: 139 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
# sync.Mutex
1+
# sync.Mutex和sync.RWMutex
22

3-
## 定义
3+
## sync.Mutex
4+
5+
### 定义
46

57
Mutex是sync包里的一个结构体类型,含义就是互斥锁。Mutex变量的默认值或者说零值是一个没有加锁的mutex,也就是当前mutex的状态是unlocked。
68

79
不要对Mutex使用值传递方式进行函数调用。
810

9-
Mutex允许一个goroutine对其加锁,其它goroutine对其解锁,不一定要加解锁在同一个goroutine里
11+
Mutex允许一个goroutine对其加锁,其它goroutine对其解锁,不要求加锁和解锁在同一个goroutine里
1012

1113
Mutex结构体类型有2个方法
1214

@@ -22,8 +24,6 @@ Mutex结构体类型有2个方法
2224
func (m *Mutex) Unlock()
2325
```
2426

25-
## 使用
26-
2727
### 不加锁
2828

2929
* 场景举例:多个 goroutine对共享变量同时执行写操作,并发是不安全的,结果和预期不符。
@@ -104,4 +104,137 @@ Mutex结构体类型有2个方法
104104
}
105105
```
106106

107-
107+
108+
109+
110+
## sync.RWMutex
111+
112+
### 定义
113+
114+
RWMutex是sync包里的一个结构体类型,含义是读写锁。RWMutex变量的零值是一个没有加锁的mutex。
115+
116+
不要对RWMutex变量使用值传递的方式进行函数调用。
117+
118+
RWMutex允许一个goroutine对其加锁,其它goroutine对其解锁,不要求加锁和解锁在同一个goroutine里。
119+
120+
RWMutex结构体类型的定义如下:
121+
122+
```go
123+
type RWMutex struct {
124+
// some fields
125+
}
126+
```
127+
128+
RWMutex结构体类型有5个方法:
129+
130+
* Lock(),加写锁。某个goroutine加了写锁后,其它goroutine不能获取读锁,也不能获取写锁
131+
132+
```go
133+
func (rw *RWMutex) Lock()
134+
```
135+
136+
* Unlock(),释放写锁。
137+
138+
```go
139+
func (rw *RWMutex) Unlock()
140+
```
141+
142+
* RLock(),加读锁。某个goroutine加了读锁后,其它goroutine可以获取读锁,但是不能获取写锁
143+
144+
```go
145+
func (rw *RWMutex) RLock()
146+
```
147+
148+
* RUnlock(),释放读锁
149+
150+
```go
151+
func (rw *RWMutex) RUnlock()
152+
```
153+
154+
* RLocker(),获取一个类型为Locker的接口,Locker类型定义了Lock()和Unlock()方法
155+
156+
```go
157+
func (rw *RWMutex) RLocker() Locker
158+
```
159+
160+
类型Locker的定义如下
161+
162+
```go
163+
type Locker interface {
164+
Lock()
165+
Unlock()
166+
}
167+
```
168+
169+
170+
171+
### 示例
172+
173+
```go
174+
package main
175+
176+
import (
177+
"fmt"
178+
"sync"
179+
)
180+
181+
type Counter struct {
182+
/*
183+
成员count:计数器
184+
成员rw: 读写锁,用于实现count的读写并发安全
185+
*/
186+
count int
187+
rw sync.RWMutex
188+
}
189+
190+
func (c *Counter) getCounter() int{
191+
/*
192+
读数据的时候加读锁
193+
*/
194+
c.rw.RLock()
195+
defer c.rw.RUnlock()
196+
return c.count
197+
}
198+
199+
func (c *Counter) add() {
200+
/*
201+
写数据的时候加写锁
202+
*/
203+
c.rw.Lock()
204+
defer c.rw.Unlock()
205+
c.count++
206+
}
207+
208+
func main() {
209+
var wg sync.WaitGroup
210+
size := 100
211+
wg.Add(size)
212+
213+
var c Counter
214+
/*
215+
开启size个goroutine对变量c的数据成员count同时进行读写操作
216+
*/
217+
for i:=0; i<size; i++ {
218+
go func() {
219+
defer wg.Done()
220+
c.getCounter()
221+
c.add()
222+
}()
223+
}
224+
wg.Wait()
225+
fmt.Println("count=", c.count)
226+
}
227+
```
228+
229+
230+
231+
## 注意事项
232+
233+
* Mutex和RWMutex都不是递归锁,不可重入
234+
235+
## References
236+
237+
https://pkg.go.dev/[email protected]#Mutex
238+
239+
https://pkg.go.dev/[email protected]#RWMutex
240+

workspace/lesson23/rwmutex.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
)
7+
8+
type Counter struct {
9+
/*
10+
成员count:计数器
11+
成员rw: 读写锁,用于实现count的读写并发安全
12+
*/
13+
count int
14+
rw sync.RWMutex
15+
}
16+
17+
func (c *Counter) getCounter() int{
18+
/*
19+
读数据的时候加读锁
20+
*/
21+
c.rw.RLock()
22+
defer c.rw.RUnlock()
23+
return c.count
24+
}
25+
26+
func (c *Counter) add() {
27+
/*
28+
写数据的时候加写锁
29+
*/
30+
c.rw.Lock()
31+
defer c.rw.Unlock()
32+
c.count++
33+
}
34+
35+
func main() {
36+
var wg sync.WaitGroup
37+
size := 100
38+
wg.Add(size)
39+
40+
var c Counter
41+
/*
42+
开启size个goroutine对变量c的数据成员count同时进行读写操作
43+
*/
44+
for i:=0; i<size; i++ {
45+
go func() {
46+
defer wg.Done()
47+
c.getCounter()
48+
c.add()
49+
}()
50+
}
51+
wg.Wait()
52+
fmt.Println("count=", c.count)
53+
}

0 commit comments

Comments
 (0)