欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

GoLang切片并發(fā)安全解決方案詳解

 更新時間:2022年10月12日 09:14:35   作者:~龐貝  
這篇文章主要介紹了GoLang切片并發(fā)安全問題的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧

1.介紹切片并發(fā)問題

關(guān)于切片的,Go語言中的切片原生支持并發(fā)嗎?

2.實(shí)踐檢驗(yàn)真理

實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),所以當(dāng)我們遇到一個不確定的問題,直接寫demo來驗(yàn)證,因?yàn)榍衅奶攸c(diǎn),我們可以分多種情況來驗(yàn)證

1.不指定索引,動態(tài)擴(kuò)容并發(fā)向切片添加數(shù)據(jù)

2.指定索引,指定容量并發(fā)向切片添加數(shù)據(jù)

  • 不指定索引,動態(tài)擴(kuò)容并發(fā)向切片添加數(shù)據(jù)

不指定索引,動態(tài)擴(kuò)容并發(fā)向切片添加數(shù)據(jù):

通過打印數(shù)據(jù)發(fā)現(xiàn)每次len與cap的結(jié)果都不一致

func concurrentAppendSliceNotForceIndex() {
	sl := make([]int, 0)
	wg := sync.WaitGroup{}
	for index := 0; index < 100; index++ {
		k := index
		wg.Add(1)
		go func(num int) {
			sl = append(sl, num)
			wg.Done()
		}(k)
	}
	wg.Wait()
	fmt.Println(sl)
	fmt.Printf("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl))
}
func main() {
	concurrentAppendSliceNotForceIndex()
	/*第一次運(yùn)行代碼后,輸出:[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*/
	//第二次運(yùn)行代碼后,輸出:省略切片元素輸出... final len(sl)=81 cap(sl)=128
	//第二次運(yùn)行代碼后,輸出:省略切片元素輸出... final len(sl)=77 cap(sl)=128
}
  • 指定索引,指定容量并發(fā)向切片添加數(shù)據(jù)

指定索引,指定容量并發(fā)向切片添加數(shù)據(jù):

通過結(jié)果我們可以發(fā)現(xiàn)符合我們的預(yù)期,長度和容量都是100

func concurrentAppendSliceForceIndex() {
	sl := make([]int, 100)
	wg := sync.WaitGroup{}
	for index := 0; index < 100; index++ {
		k := index
		wg.Add(1)
		go func(num int) {
			sl[num] = num
			wg.Done()
		}(k)
	}
	wg.Wait()
	fmt.Println(sl)
	fmt.Printf("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl))
}
func main() {
	concurrentAppendSliceForceIndex()
	/*第一次運(yùn)行代碼后,輸出:[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*/
	/*第一次運(yùn)行代碼后,輸出:[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*/
	/*第一次運(yùn)行代碼后,輸出:[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.回答切片并發(fā)安全問題

我們都知道切片是對數(shù)組的抽象,其底層就是數(shù)組,在并發(fā)下寫數(shù)據(jù)到相同的索引位會被覆蓋,并且切片也有自動擴(kuò)容的功能,當(dāng)切片要進(jìn)行擴(kuò)容時,就要替換底層的數(shù)組,在切換底層數(shù)組時,多個goroutine是同時運(yùn)行的,哪個goroutine先運(yùn)行是不確定的,不論哪個goroutine先寫入內(nèi)存,肯定就有一次寫入會覆蓋之前的寫入,所以在動態(tài)擴(kuò)容時并發(fā)寫入數(shù)組是不安全的;

所以當(dāng)別人問你slice支持并發(fā)時,你就可以這樣回答它:

當(dāng)指定索引使用切片時,切片是支持并發(fā)讀寫索引區(qū)的數(shù)據(jù)的,但是索引區(qū)的數(shù)據(jù)在并發(fā)時會被覆蓋的;當(dāng)不指定索引切片時,并且切片動態(tài)擴(kuò)容時,并發(fā)場景下擴(kuò)容會被覆蓋,所以切片是不支持并發(fā)的~。

4.解決切片并發(fā)安全問題方式

針對上述問題,我們可以多種方法來解決切片并發(fā)安全的問題:

1.加互斥鎖

2.使用channel串行化操作

3.使用sync.map代替切片

5.附

設(shè)置為1的的時候,runtime.GOMAXPROCS(1)

package main
import (
	"fmt"
	"runtime"
	"sync"
)
func concurrentAppendSliceNotForceIndex() {
	sl := make([]int, 0)
	wg := sync.WaitGroup{}
	for index := 0; index < 100; index++ {
		k := index
		wg.Add(1)
		go func(num int) {
			sl = append(sl, num)
			wg.Done()
		}(k)
	}
	wg.Wait()
	fmt.Println(sl)
	fmt.Printf("final len(sl)=%d cap(sl)=%d\n", len(sl), cap(sl))
}
func main() {
	runtime.GOMAXPROCS(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 sync.WaitGroup
var sl []int
func add() {
	for index := 0; index < 100; index++ {
		sl = append(sl, index)
	}
	wg.Done()
}
func main() {
	runtime.GOMAXPROCS(1)
	wg.Add(1)
	go add()
	wg.Wait()
	//無論執(zhí)行多少次都輸出一下結(jié)果
	fmt.Println(sl)
	fmt.Printf("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 sync.WaitGroup
var sl []int
func add() {
	for index := 0; index < 50; index++ {
		sl = append(sl, index)
	}
	wg.Done()
}
func main() {
	runtime.GOMAXPROCS(1)
	wg.Add(2)
	go add()
	go add()
	wg.Wait()
	//無論執(zhí)行多少次都輸出一下結(jié)果
	fmt.Println(sl)
	fmt.Printf("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
	*/
}

不限數(shù)量:

package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
var sl []int
func add() {
	for index := 0; index < 50; index++ {
		sl = append(sl, index)
	}
	wg.Done()
}
func main() {
	wg.Add(2)
	go add()
	go add()
	wg.Wait()
	fmt.Println(sl)
	fmt.Printf("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
	*/
}

加鎖

package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
var sl []int
var lock sync.Mutex
func add() {
	for index := 0; index < 50; index++ {
		lock.Lock()
		sl = append(sl, index)
		lock.Unlock()
	}
	wg.Done()
}
func main() {
	wg.Add(2)
	go add()
	go add()
	wg.Wait()
	fmt.Println(sl)
	fmt.Printf("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
	*/
}

到此這篇關(guān)于GoLang切片并發(fā)安全解決方案詳解的文章就介紹到這了,更多相關(guān)GoLang切片并發(fā)安全內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言開發(fā)k8s之Service操作解析

    Go語言開發(fā)k8s之Service操作解析

    這篇文章主要為大家介紹了Go語言開發(fā)k8s之Service操作解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • go語言使用pipe讀取子進(jìn)程標(biāo)準(zhǔn)輸出的方法

    go語言使用pipe讀取子進(jìn)程標(biāo)準(zhǔn)輸出的方法

    這篇文章主要介紹了go語言使用pipe讀取子進(jìn)程標(biāo)準(zhǔn)輸出的方法,實(shí)例分析了Go語言針對進(jìn)程操作的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • 快速掌握Go 語言 HTTP 標(biāo)準(zhǔn)庫的實(shí)現(xiàn)方法

    快速掌握Go 語言 HTTP 標(biāo)準(zhǔn)庫的實(shí)現(xiàn)方法

    基于HTTP構(gòu)建的服務(wù)標(biāo)準(zhǔn)模型包括兩個端,客戶端(Client)和服務(wù)端(Server),這篇文章主要介紹了Go 語言HTTP標(biāo)準(zhǔn)庫的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2022-07-07
  • Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼

    Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼

    本文主要介紹了Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • golang切片拷貝的實(shí)現(xiàn)

    golang切片拷貝的實(shí)現(xiàn)

    在Golang中,切片的淺拷貝只復(fù)制指向?qū)ο蟮闹羔?而深拷貝則復(fù)制數(shù)據(jù)本身,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • golang微服務(wù)框架kratos實(shí)現(xiàn)Socket.IO服務(wù)的方法

    golang微服務(wù)框架kratos實(shí)現(xiàn)Socket.IO服務(wù)的方法

    本文主要介紹了golang微服務(wù)框架kratos實(shí)現(xiàn)Socket.IO服務(wù)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 一個Pod調(diào)度失敗后重新觸發(fā)調(diào)度的所有情況分析

    一個Pod調(diào)度失敗后重新觸發(fā)調(diào)度的所有情況分析

    這篇文章主要為大家介紹了一個Pod調(diào)度失敗后重新觸發(fā)調(diào)度的所有情況分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • golang中的select關(guān)鍵字用法總結(jié)

    golang中的select關(guān)鍵字用法總結(jié)

    這篇文章主要介紹了golang中的select關(guān)鍵字用法總結(jié),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Go語言中http.ResponseWriter接口

    Go語言中http.ResponseWriter接口

    http.ResponseWriter是Go語言中用來設(shè)置HTTP響應(yīng)的接口,本文主要介紹了Go語言中http.ResponseWriter接口,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • Go語言深度拷貝工具deepcopy的使用教程

    Go語言深度拷貝工具deepcopy的使用教程

    今天給大家推薦的工具是deepcopy,一個可以對指針、接口、切片、結(jié)構(gòu)體、Map都能進(jìn)行深拷貝的工具,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2022-09-09

最新評論