Skip to content

Commit ec20162

Browse files
authored
Merge pull request #560 from devlights/add-slice-not-threadsafe-example
2 parents 3767211 + c0e5f63 commit ec20162

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version: '3'
2+
3+
tasks:
4+
fmt:
5+
cmds:
6+
- go fmt ./...
7+
vet:
8+
cmds:
9+
- go vet ./...
10+
run:
11+
cmds:
12+
- cmd: for i in {1..10} ; do go run race/main.go; done
13+
silent: true
14+
run-notrace:
15+
cmds:
16+
- cmd: for i in {1..10} ; do go run notrace/main.go; done
17+
silent: true
18+
run-notrace2:
19+
cmds:
20+
- cmd: for i in {1..10} ; do go run notrace2/main.go; done
21+
silent: true
22+
run-with-raceoption:
23+
cmds:
24+
- cmd: go run -race race/main.go
25+
ignore_error: true
26+
- go run -race notrace/main.go
27+
- go run -race notrace2/main.go
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// スライス操作 (スライスヘッダの書き換え)はスレッドセーフでは無いというのを示すサンプルです。
2+
// 本サンプルはデータ競合が発生しません。
3+
//
4+
// REFERENCES:
5+
// - https://stackoverflow.com/questions/44152988/append-not-thread-safe
6+
// - https://stackoverflow.com/questions/49879322/can-i-concurrently-write-different-slice-elements
7+
package main
8+
9+
import (
10+
"flag"
11+
"fmt"
12+
"strconv"
13+
"sync"
14+
)
15+
16+
type data struct {
17+
value string
18+
}
19+
20+
func (me data) String() string {
21+
return me.value
22+
}
23+
24+
func main() {
25+
var (
26+
verbose = flag.Bool("verbose", false, "verbose output")
27+
)
28+
flag.Parse()
29+
30+
var (
31+
mu = sync.Mutex{}
32+
src = make([]data, 100)
33+
dst = make([]data, 0)
34+
)
35+
36+
for i := 0; i < len(src); i++ {
37+
src[i].value = strconv.Itoa(i)
38+
}
39+
40+
wg := sync.WaitGroup{}
41+
for _, v := range src {
42+
wg.Add(1)
43+
go func(v data) {
44+
defer wg.Done()
45+
46+
var tmp data
47+
tmp.value = v.value
48+
49+
mu.Lock()
50+
dst = append(dst, tmp)
51+
mu.Unlock()
52+
}(v)
53+
}
54+
55+
wg.Wait()
56+
57+
fmt.Printf("src-len=%d\tdst-len=%d\n", len(src), len(dst))
58+
59+
if *verbose {
60+
fmt.Println("=========== SRC ===========")
61+
for _, v := range src {
62+
fmt.Println(v)
63+
}
64+
fmt.Println("=========== DST ===========")
65+
for _, v := range dst {
66+
fmt.Println(v)
67+
}
68+
}
69+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// スライス操作 (スライスヘッダの書き換え)はスレッドセーフでは無いというのを示すサンプルです。
2+
// 本サンプルはデータ競合が発生しません。
3+
//
4+
// REFERENCES:
5+
// - https://stackoverflow.com/questions/44152988/append-not-thread-safe
6+
// - https://stackoverflow.com/questions/49879322/can-i-concurrently-write-different-slice-elements
7+
package main
8+
9+
import (
10+
"flag"
11+
"fmt"
12+
"strconv"
13+
"sync"
14+
)
15+
16+
type data struct {
17+
value string
18+
}
19+
20+
func (me data) String() string {
21+
return me.value
22+
}
23+
24+
func main() {
25+
var (
26+
verbose = flag.Bool("verbose", false, "verbose output")
27+
)
28+
flag.Parse()
29+
30+
var (
31+
src = make([]data, 100)
32+
dst = make([]data, len(src))
33+
)
34+
35+
for i := 0; i < len(src); i++ {
36+
src[i].value = strconv.Itoa(i)
37+
}
38+
39+
wg := sync.WaitGroup{}
40+
for i, v := range src {
41+
wg.Add(1)
42+
go func(i int, v data) {
43+
defer wg.Done()
44+
45+
var tmp data
46+
tmp.value = v.value
47+
48+
dst[i] = tmp
49+
}(i, v)
50+
}
51+
52+
wg.Wait()
53+
54+
fmt.Printf("src-len=%d\tdst-len=%d\n", len(src), len(dst))
55+
56+
if *verbose {
57+
fmt.Println("=========== SRC ===========")
58+
for _, v := range src {
59+
fmt.Println(v)
60+
}
61+
fmt.Println("=========== DST ===========")
62+
for _, v := range dst {
63+
fmt.Println(v)
64+
}
65+
}
66+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// スライス操作 (スライスヘッダの書き換え)はスレッドセーフでは無いというのを示すサンプルです。
2+
// 本サンプルはデータ競合が発生しています。
3+
//
4+
// REFERENCES:
5+
// - https://stackoverflow.com/questions/44152988/append-not-thread-safe
6+
// - https://stackoverflow.com/questions/49879322/can-i-concurrently-write-different-slice-elements
7+
package main
8+
9+
import (
10+
"flag"
11+
"fmt"
12+
"strconv"
13+
"sync"
14+
)
15+
16+
type data struct {
17+
value string
18+
}
19+
20+
func (me data) String() string {
21+
return me.value
22+
}
23+
24+
func main() {
25+
var (
26+
verbose = flag.Bool("verbose", false, "verbose output")
27+
)
28+
flag.Parse()
29+
30+
var (
31+
src = make([]data, 100)
32+
dst = make([]data, 0)
33+
)
34+
35+
for i := 0; i < len(src); i++ {
36+
src[i].value = strconv.Itoa(i)
37+
}
38+
39+
wg := sync.WaitGroup{}
40+
for _, v := range src {
41+
wg.Add(1)
42+
go func(v data) {
43+
defer wg.Done()
44+
45+
var tmp data
46+
tmp.value = v.value
47+
48+
dst = append(dst, tmp)
49+
}(v)
50+
}
51+
52+
wg.Wait()
53+
54+
fmt.Printf("src-len=%d\tdst-len=%d\n", len(src), len(dst))
55+
56+
if *verbose {
57+
fmt.Println("=========== SRC ===========")
58+
for _, v := range src {
59+
fmt.Println(v)
60+
}
61+
fmt.Println("=========== DST ===========")
62+
for _, v := range dst {
63+
fmt.Println(v)
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)