Skip to content

Commit 79b8f59

Browse files
authored
Merge pull request #777 from devlights/add-rwmutex-trylock-example
2 parents 8ce188f + b108b5c commit 79b8f59

File tree

5 files changed

+232
-15
lines changed

5 files changed

+232
-15
lines changed

examples/basic/syncs/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
| use_pool.go | syncs_use_pool | sync.Poolのサンプルです |
2121
| mutex_trylock.go | syncs_mutex_trylock | Go 1.18 で追加された mutex.TryLock() についてのサンプルです。 |
2222
| use_rwmutex.go | syncs_use_rwmutex | sync.RWMutex のサンプルです。 |
23+
| rwmute_trylock.go | syncs_rwmutex_trylock | Go 1.18 で追加された RWMutex の TryLock() と TryRLock() のサンプルです。 |

examples/basic/syncs/examples.go

+1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ func (r *register) Regist(m mapping.ExampleMapping) {
2929
m["syncs_use_oncevalues"] = UseOnceValues
3030
m["syncs_use_pool"] = UsePool
3131
m["syncs_mutex_trylock"] = MutexTryLock
32+
m["syncs_rwmutex_trylock"] = RWMutexTryLock
3233
}

examples/basic/syncs/mutex_trylock.go

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func MutexTryLock() error {
4747

4848
// ここは mutex がアンロックされているのでロックが取れる
4949
printStatus()
50+
defer m.Unlock()
5051

5152
return nil
5253

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package syncs
2+
3+
import (
4+
"context"
5+
"log"
6+
"sync"
7+
"time"
8+
)
9+
10+
// RWMutexTryLock は、Go 1.18 で追加された RWMutex の TryLock() と TryRLock() のサンプルです。
11+
//
12+
// 使い方としては、Mutex.TryLock() と同じ。RLockのTry版がTryRLock, LockのTry版がTryLockとなる。
13+
//
14+
// # REFERENCES
15+
// - https://pkg.go.dev/[email protected]#RWMutex.TryLock
16+
// - https://pkg.go.dev/[email protected]#RWMutex.TryRLock
17+
func RWMutexTryLock() error {
18+
//
19+
// 3つのゴルーチンがあり、2つは値の読み取り(RLock)、1つは値の書き込み(Lock)を行う。
20+
// それぞれ、ロックに入る前に TryRLock/TryLock により、ロック可能かどうかを確認する。
21+
//
22+
23+
log.SetFlags(log.Lmicroseconds)
24+
25+
var (
26+
v int64
27+
m sync.RWMutex
28+
read = func(ctx context.Context, prefix string, interval time.Duration) {
29+
for {
30+
select {
31+
case <-ctx.Done():
32+
return
33+
default:
34+
}
35+
36+
func() {
37+
log.Printf("[%s] <<<", prefix)
38+
for !m.TryRLock() {
39+
log.Printf("[%s] TryRLock=false", prefix)
40+
41+
select {
42+
case <-ctx.Done():
43+
return
44+
case <-time.After(100 * time.Millisecond):
45+
}
46+
}
47+
48+
log.Printf("[%s] %v", prefix, v)
49+
50+
m.RUnlock()
51+
log.Printf("[%s] >>>", prefix)
52+
53+
select {
54+
case <-ctx.Done():
55+
case <-time.After(interval):
56+
}
57+
}()
58+
}
59+
}
60+
write = func(ctx context.Context, prefix string, interval time.Duration) {
61+
for {
62+
select {
63+
case <-ctx.Done():
64+
return
65+
default:
66+
}
67+
68+
func() {
69+
log.Printf("[%s] <<<", prefix)
70+
for !m.TryLock() {
71+
log.Printf("[%s] TryLock=false", prefix)
72+
73+
select {
74+
case <-ctx.Done():
75+
return
76+
case <-time.After(100 * time.Millisecond):
77+
}
78+
}
79+
80+
old := v
81+
v++
82+
log.Printf("[%s] %v --> %v", prefix, old, v)
83+
84+
m.Unlock()
85+
log.Printf("[%s] >>>", prefix)
86+
87+
select {
88+
case <-ctx.Done():
89+
case <-time.After(interval):
90+
}
91+
}()
92+
}
93+
}
94+
)
95+
96+
ctx, cxl := context.WithTimeout(context.Background(), 2*time.Second)
97+
defer cxl()
98+
99+
go read(ctx, "READ-1", 500*time.Millisecond)
100+
go read(ctx, "READ-2", 500*time.Millisecond)
101+
go write(ctx, "WRITE-1", 500*time.Millisecond)
102+
103+
<-ctx.Done()
104+
log.Println("DONE")
105+
106+
return nil
107+
108+
/*
109+
$ task
110+
task: [build] go build .
111+
task: [run] ./try-golang -onetime
112+
113+
ENTER EXAMPLE NAME: syncs_rwmutex_trylock
114+
115+
[Name] "syncs_rwmutex_trylock"
116+
06:00:30.134950 [WRITE-1] <<<
117+
06:00:30.135052 [WRITE-1] 0 --> 1
118+
06:00:30.135059 [WRITE-1] >>>
119+
06:00:30.134976 [READ-2] <<<
120+
06:00:30.135079 [READ-2] 1
121+
06:00:30.135085 [READ-2] >>>
122+
06:00:30.134970 [READ-1] <<<
123+
06:00:30.135264 [READ-1] 1
124+
06:00:30.135268 [READ-1] >>>
125+
06:00:30.635750 [READ-1] <<<
126+
06:00:30.635773 [READ-1] 1
127+
06:00:30.635776 [READ-1] >>>
128+
06:00:30.635762 [READ-2] <<<
129+
06:00:30.635803 [READ-2] 1
130+
06:00:30.635812 [READ-2] >>>
131+
06:00:30.635787 [WRITE-1] <<<
132+
06:00:30.635855 [WRITE-1] 1 --> 2
133+
06:00:30.635867 [WRITE-1] >>>
134+
06:00:31.136388 [WRITE-1] <<<
135+
06:00:31.136406 [READ-1] <<<
136+
06:00:31.136411 [WRITE-1] 2 --> 3
137+
06:00:31.136423 [WRITE-1] >>>
138+
06:00:31.136422 [READ-2] <<<
139+
06:00:31.136430 [READ-2] 3
140+
06:00:31.136438 [READ-2] >>>
141+
06:00:31.136415 [READ-1] TryRLock=false
142+
06:00:31.236739 [READ-1] 3
143+
06:00:31.236767 [READ-1] >>>
144+
06:00:31.637314 [WRITE-1] <<<
145+
06:00:31.637340 [READ-2] <<<
146+
06:00:31.637367 [READ-2] TryRLock=false
147+
06:00:31.637335 [WRITE-1] 3 --> 4
148+
06:00:31.637405 [WRITE-1] >>>
149+
06:00:31.737604 [READ-2] 4
150+
06:00:31.737631 [READ-2] >>>
151+
06:00:31.737631 [READ-1] <<<
152+
06:00:31.737644 [READ-1] 4
153+
06:00:31.737653 [READ-1] >>>
154+
06:00:32.135034 DONE
155+
156+
157+
[Elapsed] 2.000177751s
158+
*/
159+
160+
}

examples/basic/syncs/use_rwmutex.go

+69-15
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ func UseRWMutex() error {
5151
}
5252

5353
func() {
54+
log.Printf("[%s] <<<", prefix)
5455
m.RLock()
55-
defer m.RUnlock()
56-
57-
log.Printf("[%s] %v", prefix, v)
56+
{
57+
log.Printf("[%s] %v", prefix, v)
58+
}
59+
m.RUnlock()
60+
log.Printf("[%s] >>>", prefix)
5861

5962
select {
6063
case <-ctx.Done():
@@ -65,22 +68,22 @@ func UseRWMutex() error {
6568
}
6669
write = func(ctx context.Context, prefix string, interval time.Duration) {
6770
for {
68-
// 1秒間、RLockできる猶予を与える
6971
select {
7072
case <-ctx.Done():
7173
return
72-
case <-time.After(1 * time.Second):
74+
default:
7375
}
7476

75-
// ここから interval の間は排他ロックとなる
7677
func() {
78+
log.Printf("[%s] <<<", prefix)
7779
m.Lock()
78-
defer m.Unlock()
79-
80-
old := v
81-
v++
82-
83-
log.Printf("[%s] %v --> %v", prefix, old, v)
80+
{
81+
old := v
82+
v++
83+
log.Printf("[%s] %v --> %v", prefix, old, v)
84+
}
85+
m.Unlock()
86+
log.Printf("[%s] >>>", prefix)
8487

8588
select {
8689
case <-ctx.Done():
@@ -91,15 +94,66 @@ func UseRWMutex() error {
9194
}
9295
)
9396

94-
ctx, cxl := context.WithTimeout(context.Background(), 10*time.Second)
97+
ctx, cxl := context.WithTimeout(context.Background(), 2*time.Second)
9598
defer cxl()
9699

97100
go read(ctx, "READ-1", 500*time.Millisecond)
98-
go read(ctx, "READ-2", 250*time.Millisecond)
99-
go write(ctx, "WRITE-1", 2*time.Second)
101+
go read(ctx, "READ-2", 500*time.Millisecond)
102+
go write(ctx, "WRITE-1", 500*time.Millisecond)
100103

101104
<-ctx.Done()
102105
log.Println("DONE")
103106

104107
return nil
108+
109+
/*
110+
$ task
111+
task: [build] go build .
112+
task: [run] ./try-golang -onetime
113+
114+
ENTER EXAMPLE NAME: syncs_use_rwmutex
115+
116+
[Name] "syncs_use_rwmutex"
117+
05:57:00.082899 [WRITE-1] <<<
118+
05:57:00.082972 [READ-2] <<<
119+
05:57:00.083014 [WRITE-1] 0 --> 1
120+
05:57:00.083022 [WRITE-1] >>>
121+
05:57:00.083040 [READ-2] 1
122+
05:57:00.083052 [READ-2] >>>
123+
05:57:00.082938 [READ-1] <<<
124+
05:57:00.083208 [READ-1] 1
125+
05:57:00.083216 [READ-1] >>>
126+
05:57:00.583383 [READ-1] <<<
127+
05:57:00.583406 [READ-1] 1
128+
05:57:00.583409 [READ-1] >>>
129+
05:57:00.583422 [WRITE-1] <<<
130+
05:57:00.583406 [READ-2] <<<
131+
05:57:00.583490 [WRITE-1] 1 --> 2
132+
05:57:00.583512 [WRITE-1] >>>
133+
05:57:00.583518 [READ-2] 2
134+
05:57:00.583523 [READ-2] >>>
135+
05:57:01.083740 [READ-1] <<<
136+
05:57:01.083786 [READ-1] 2
137+
05:57:01.083801 [READ-1] >>>
138+
05:57:01.083774 [READ-2] <<<
139+
05:57:01.083829 [READ-2] 2
140+
05:57:01.083833 [READ-2] >>>
141+
05:57:01.083779 [WRITE-1] <<<
142+
05:57:01.083837 [WRITE-1] 2 --> 3
143+
05:57:01.083840 [WRITE-1] >>>
144+
05:57:01.584523 [WRITE-1] <<<
145+
05:57:01.584552 [READ-2] <<<
146+
05:57:01.584553 [WRITE-1] 3 --> 4
147+
05:57:01.584595 [WRITE-1] >>>
148+
05:57:01.584607 [READ-2] 4
149+
05:57:01.584617 [READ-2] >>>
150+
05:57:01.584542 [READ-1] <<<
151+
05:57:01.584623 [READ-1] 4
152+
05:57:01.584629 [READ-1] >>>
153+
05:57:02.083111 DONE
154+
155+
156+
[Elapsed] 2.000292011s
157+
*/
158+
105159
}

0 commit comments

Comments
 (0)