1.Introduce the problem of slice concurrency
Regarding slices, does slices natively support concurrency in Go language?
2. Practice tests the truth
Practice is the only criterion for testing truth, so when we encounter an uncertain problem, we can directly write a demo to verify it. Because of the characteristics of slices, we can verify it in multiple situations.
1. Dynamically expand and add data to slices without specifying an index
2. Specify the index and specify the capacity to add data to the slice concurrently
- Without specifying an index, dynamically expand and concurrently add data to slices
Without specifying an index, dynamically expand and concurrently add data to the slice:
By printing the data, it is found that the results of each len and cap are not consistent.
func concurrentAppendSliceNotForceIndex() { sl := make([]int, 0) wg := {} for index := 0; index < 100; index++ { k := index (1) go func(num int) { sl = append(sl, num) () }(k) } () (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) } func main() { concurrentAppendSliceNotForceIndex() /*After the first time the code is run, the output is: [2 0 1 5 6 7 8 9 10 4 17 11 12 13 14 15 16 21 18 19 20 23 22 24 25 26 39 27 28 29 30 31 35 55 54 56 57 58 59 60 61 62 64 63 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 86 91 92 93 94 96 95 97 98 99] Final len(sl)=74 cap(sl)=128*/ //After running the code for the second time, the output: omit the output of the slice element... final len(sl)=81 cap(sl)=128 //After running the code for the second time, the output: omit the output of the slice element... final len(sl)=77 cap(sl)=128}
- Specify index, specify capacity to add data to slices concurrently
Specify the index, specify the capacity to add data to the slice concurrently:
Through the results we can find that the length and capacity are 100
func concurrentAppendSliceForceIndex() { sl := make([]int, 100) wg := {} for index := 0; index < 100; index++ { k := index (1) go func(num int) { sl[num] = num () }(k) } () (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) } func main() { concurrentAppendSliceForceIndex() /* After the first run of the code, the output is: [0 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 7 9 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99] Final len(sl)=100 cap(sl)=100*/ /* After the first run of the code, the output is: [0 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 7 9 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99] Final len(sl)=100 cap(sl)=100*/ /* After the first run of the code, the output is: [0 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 7 9 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99] Final len(sl)=100 cap(sl)=100*/ }
3. Answer the security questions about slicing concurrency
We all know that slices are abstractions of arrays. The underlying layer is an array. Writing data to the same index bits under concurrency will be overwritten. And slices also have the function of automatic expansion. When the slice is to be expanded, the underlying array must be replaced. When switching the underlying array, multiple goroutines run at the same time. It is uncertain which goroutine is first run. No matter which goroutine is written to memory first, there will definitely be a write that will overwrite the previous writes. Therefore, it is not safe to write to the array concurrently during dynamic expansion;
So when someone asks you that slice supports concurrency, you can answer it like this:
When a slice is used in a specified index, the slice supports concurrent reading and writing data in the index area, but the data in the index area will be overwritten when concurrent; when no index slice is specified and the slice dynamically expands the capacity, the expansion in the concurrent scenario will be overwritten, so the slice does not support concurrency ~.
4. How to solve the security problem of slicing concurrency
In response to the above problems, we can solve the problem of slicing concurrency safety in a variety of ways:
1. Add a mutex lock
2. Use channel to serialize operations
3. Use instead of slices
5. Attached
When set to 1, (1)
package main import ( "fmt" "runtime" "sync" ) func concurrentAppendSliceNotForceIndex() { sl := make([]int, 0) wg := {} for index := 0; index < 100; index++ { k := index (1) go func(num int) { sl = append(sl, num) () }(k) } () (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) } func main() { (1) concurrentAppendSliceNotForceIndex() /* [99 0 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 5 5 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] final len(sl)=100 cap(sl)=128 */ /* [13 0 1 2 3 4 5 6 7 8 9 10 11 12 99 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 5 5 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] final len(sl)=100 cap(sl)=128 */ /* [10 0 1 2 3 4 5 6 7 8 9 99 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 5 5 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] final len(sl)=100 cap(sl)=128 */ }
package main import ( "fmt" "runtime" "sync" ) var wg var sl []int func add() { for index := 0; index < 100; index++ { sl = append(sl, index) } () } func main() { (1) (1) go add() () //No matter how many times you execute, you will output the result (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) /* [0 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 6 3 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] final len(sl)=100 cap(sl)=128 */ }
package main import ( "fmt" "runtime" "sync" ) var wg var sl []int func add() { for index := 0; index < 50; index++ { sl = append(sl, index) } () } func main() { (1) (2) go add() go add() () //No matter how many times you execute, you will output the result (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) /* [0 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 0 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] final len(sl)=100 cap(sl)=128 */ }
Unlimited quantity:
package main import ( "fmt" "sync" ) var wg var sl []int func add() { for index := 0; index < 50; index++ { sl = append(sl, index) } () } func main() { (2) go add() go add() () (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) /* [0 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 0 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] final len(sl)=82 cap(sl)=128 */ }
Add lock
package main import ( "fmt" "sync" ) var wg var sl []int var lock func add() { for index := 0; index < 50; index++ { () sl = append(sl, index) () } () } func main() { (2) go add() go add() () (sl) ("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl)) /* [0 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 0 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] final len(sl)=100 cap(sl)=128 */ /* [0 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 0 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 33 34 35 3 6 37 38 39 40 41 42 43 44 45 46 47 48 49] final len(sl)=100 cap(sl)=128 */ }
This is the end of this article about the detailed explanation of GoLang slice concurrency security solution. For more related GoLang slice concurrency security content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!