閉包,sync使用細節

代碼

先看代碼如下:

func main() {var a []intfor i := 0; i < 100; i++ {go func() {a = append(a, i)}()}time.Sleep(2 * time.Second)fmt.Println(a)
}

這段測試代碼是想要一個元素為0到100的切片,但是這一小段代碼隱藏了很多的問題。

閉包函數

先看這段代碼的執行結果:

[10 12 13 13 13 13 21 24 25 28 28 28 28 28 28 29 29 29 36 38 39 39 40 41 41 41 41 41 41 45 45 45 45 46 47 48 49 50 51 52 61 61 61 61 61 61 61 61 61 61 73 73 74 74 75 76 76 77 77 77 77 77 77 77 77 77 83 85 85 88 88 89 91 92 93 93 93 93 93 93 93 93 100 100 100 100 100 100 100]

可以發現有很多元素是相同的,這就是這段代碼的第一個錯誤:使用閉包函數的時候,代碼中這種傳遞參數i的方法并非深copy,而是傳遞變量指針。解釋一下產生這種情況的原因:在并發執行時由于某一個協程修改了i的值,導致多個協程append的時候變量**i**的值發生變化,從而導致有多個重復的元素
將代碼修改為:

func main() {var a []intfor i := 0; i < 100; i++ {go func(i int) {a = append(a, i)}(i)}time.Sleep(2 * time.Second)fmt.Println(a)
}

執行結果為:

[5 4 8 7 2 12 15 13 14 24 22 23 25 18 21 17 20 28 29 31 30 32 33 34 35 36 37 38 39 41 40 42 44 50 45 48 49 55 51 52 53 54 46 47 57 56 58 59 60 65 61 62 63 64 68 66 67 70 69 72 74 71 73 75 76 80 77 78 79 86 81 82 83 85 89 87 88 84 90 91 92 95 93 94 97 96 98 99]

可以看到沒有重復元素了,但是卻缺少一些元素,這就引出了第二個問題。

多個協程的競爭問題

如上述代碼,執行多次都會發現每次執行的結果都會少一些元素,其實真正的原因是沒有對于競爭的協程加互斥鎖,導致資源的丟失
解釋這個問題要對go的數組、切片、以及append機制有一些了解,參考:

Arrays, slices (and strings): The mechanics of 'append'

現在知道我們聲明的切片不同于數組,在每次append的時候我們會伴隨著內存copy以達到自動擴容目的,在A協程讀出a的內存數據時,B協程完成了寫入操作,此時A繼續append并賦值就會導致,協程B的更新結果丟失。
假如我們將切片換成數組就不存在這個問題:


func main() {var a [100]intfor i := 0; i < 100; i++ {go func(i int) {// a = append(a, i)a[i] = i}(i)}time.Sleep(2 * time.Second)fmt.Println(a)
}

結果

[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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]

或者互斥鎖,

func main() {var a []intvar mu sync.Mutexfor i := 0; i < 100; i++ {go func(i int) {mu.Lock()a = append(a, i)mu.Unlock()}(i)}time.Sleep(2 * time.Second)fmt.Println(a)
}

結果

[1 0 2 9 7 8 10 4 5 3 11 6 12 14 13 16 15 23 20 21 22 19 25 24 17 26 18 27 28 29 32 30 31 34 35 36 40 33 37 39 38 42 43 41 44 51 45 49 50 55 52 53 48 54 46 47 57 56 58 59 60 64 61 62 63 68 72 70 71 74 69 75 73 65 66 67 76 79 77 78 85 80 81 82 83 84 86 88 87 90 89 91 92 93 96 94 95 97 98 99]

結論

  • 閉包使用注意變量傳遞是指針還是值,及注意閉包變量的兩種傳遞方式。
  • 注意線程安全。

結語

希望大家一起學習,一起交流,一起進步!

聯系我
qq:820932773
gmail: jdqaffairs@gmail.com

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275839.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275839.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275839.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

dynamic 儀表板_儀表板完成百萬美元交易

dynamic 儀表板問題 (The Problem) Anybody dealing with tech products and data-focused services runs into the same fundamental problem: what you do is technical but non-technical people control the budget. In other words:任何處理高科技產品和以數據為中心的服務…

checkStyle -- 代碼風格一致

download page: http://sourceforge.net/project/showfiles.php?group_id80344&package_id107587 轉載于:https://www.cnblogs.com/xuqiang/archive/2010/10/26/1953431.html

在線VS Code閱讀源碼神器 github1s

大家好&#xff0c;我是若川。github1s大部分人知道了&#xff0c;但還是有一部分不知道。我在掘金發過沸點和知乎發過想法還是有挺多人不知道&#xff0c;所以再發公眾號推薦下。點擊下方卡片關注我、加個星標。學習源碼整體架構系列、年度總結、JS基礎系列近日&#xff0c;一…

lenze變頻器怎么更改地址_英威騰變頻器GD300維修

英威騰變頻器GD300維修英威騰變頻器GD300維修41. 問題&#xff1a;變頻器跟PLC采用485通訊不上答&#xff1a;1.檢查變頻器的通訊地址是否正確&#xff0c;如果采用通訊啟動&#xff0c;檢查P0.01是否為1&#xff0c;如果通過通訊設定頻率&#xff0c;檢查P0.068&#xff0c;P0…

代碼設計的基礎原則_設計原則:良好設計的基礎

代碼設計的基礎原則As designers, it’s our goal to pass information in the most pleasing way possible. Starting out, there’s a wealth of literature to read and videos to watch that can get quite overwhelming to take in at a glance. People take different ro…

SQL根據細粒度為天的查詢

當我們集成了一些前端框架&#xff0c;在某些展示頁面上往往具有某些查詢條件。而這其中日期查詢的處理又較為麻煩&#xff0c;此處&#xff0c;我羅列了一種當前臺上傳了一種默認的date格式的日期查詢數據至后臺未經Controller或Service層處理直接在SQL中處理的一種方式——即…

企業生產經營相關英文及縮寫之(11)--Genenic 普通書寫

Genenic 普通書寫 ASAP As soon as possible 盡早 BCC Blink Carbon Copy 無信頭抄送&#xff0c;無信頭副本 BR Best Regards 最誠致的問候 BTW By the way 順便問一下 CC Carbon Copy …

java金額類型_Java中存儲金額用什么數據類型?

很早之前, 記得一次面試, 面試官問存儲金錢用什么數據類型? 當時只知道8種數據類型(boolean, byte, short, int, long, float, double, char)的我, 回答了double, 因為我覺得double是雙精度類型, 最適合, 但是面試官告訴我應該用BigDecimal! 最近在做支付的項目, 才對這種數據…

信息技術與信息革命

信息資源管理學什么 圍繞 信息這份戰略資源&#xff0c;從信息資源的管理角度出發&#xff0c;以信息系統為主要研究對象&#xff0c; 研討了信息系統規劃&#xff0c;信息系統開發 信息系統的內容&#xff0c;信息系統安全以及信息資源管理中 涉及的法律法規 知識框架 信息技術…

React Hooks 不知道怎么學?看這篇

大家好&#xff0c;我是若川。最近跟朋友聊技術&#xff0c;發現越來越多的大廠&#xff0c;都優先考慮用 React 做項目&#xff0c;在面試中也經常會考察對 React Hooks 的理解。其實&#xff0c;我一直覺得&#xff0c;React 才是前端的正確打開方式。當然&#xff0c;并不是…

數字與企鵝的戰爭,看周紅衣的高明之處

本文非原創&#xff0c;轉自月光    360與QQ最近的一輪大戰已經接近尾聲&#xff0c;毫無疑問的是&#xff0c;360在這一輪對決中以勝利告終。這場戰爭持續了整整一個月零兩天&#xff0c;先后經歷了幾次小小的高潮&#xff0c;最終周鴻祎祭出絕招&#xff0c;秒殺群雄&#…

ui原型設計工具_UI設計師的工具包,用于專業模型,原型和產品插圖

ui原型設計工具This is a followup to my previous article 這是我上一篇文章的后續 visual tools for UX Designers視覺工具Tools don’t make designs better– you do! It doesn’t matter if you paid a lot of money for the latest software, or if you simply have a p…

java wsdl xfire_java調用wsdl xfire和cxf兩種方式

xfire 如下&#xff1a;String spID "";String password "";String accessCode "";String content "";String mobileString "";String url "";String operateName "Submit";Object[] object newObject…

請求與響應

HTTP 請求與響應 HTTP 請求的組成的四部分&#xff1a; 1 動詞 路徑 協議/版本2 Key1: value12 Key2: value22 Key3: value32 Content-Type: application/x-www-form-urlencoded2 Host: www.baidu.com2 User-Agent: curl/7.54.034 要上傳的數據 關于以上各部分內容的碎碎念&…

前端 Offer 提速:如何寫出有亮點的簡歷

大家好&#xff0c;我是若川。今天推薦一篇8年工作經驗字節大佬的文章&#xff0c;如何寫出有亮點的簡歷。可以收藏常看。點擊下方卡片關注我、加個星標。學習源碼整體架構系列、年度總結、JS基礎系列先來個靈魂拷問&#xff1a;「你與他人相比&#xff0c;有什么能形成明顯區分…

2008中的membership profile操作(轉)

<profile > <properties> <add name"jimmy" /> </< span>properties> </< span>profile> 然后就那么簡單,后臺就能通過Profile拿到: Profile.jimmy "Pumpkin Ravioli"; 然后~通過這種方式就跟Session一樣&a…

css網格_一個CSS網格可以全部統治

css網格The case for using one CSS grid for your entire website在整個網站上使用一個CSS網格的情況 CSS網格與Flexbox (CSS Grid vs Flexbox) In the dark ages, we used table, a few years ago we used float and before today most of us used flex . Of course, these …

java 高級泛型_Java 泛型高級

1、限制泛型可用類型在定義泛型類別時&#xff0c;預設可以使用任何的類型來實例化泛型中的類型&#xff0c;但是如果想要限制使用泛型的類別時&#xff0c;只能用某個特定類型或者其子類型才能實例化該類型時&#xff0c;使用extends關鍵字指定這個類型必須是繼承某個類&#…

做Web前端開發的你必須會這幾點!

1、Web開發分類與區別 人們通常將Web分為前端和后端&#xff0c;前端相關的職位有前端設計師(UI/UE)&#xff0c;前端開發工程師&#xff0c;后端相關的有后端開發工程師。 2、技術棧區別 看各大招聘網站上&#xff0c;公司對前端開發工程師的要求莫過于精通HTML&#xff0c;CS…

PDA開發系列:GPS模塊的調用

摘要在wince6.0中&#xff0c;要調用GPS模塊&#xff0c;其實是一件很容易的事情。 正文在wince6.0中&#xff0c;如果要調用GPS模塊&#xff0c;其實很簡單&#xff0c;微軟已經為我們做好了這一切&#xff0c;我們只需要在自己的解決方案中&#xff0c;添加對Microsoft.Windo…