《Go 語言併發之道》讀書筆記(二)

来源:https://www.cnblogs.com/dk168/archive/2022/11/16/16896880.html
-Advertisement-
Play Games

大家好,我是棧長。 今天給大家通報一則框架更新消息,時隔兩個月,Spring Cloud 2021.0.5 最新版發佈了,來看下最新的 Spring Cloud 版本情況: Spring Cloud 無疑是現在 Java 微服務事實上的標準,完全基於 Spring Boot 構建,依賴 Spring ...


今天這篇筆記重點講goroutine

首先怎麼定義goroutine

很簡單,在方法前面加上go就可以了

func main() {
	go sayHello()
}

func sayHello() {
	fmt.Println("hello")
}

也可以直接這樣寫, 基於匿名函數

go func() {
	fmt.Println("hello")
}()

go 語言至少有一個main goroutine, 另外調用的sayhello goroutine和main goroutine併發執行,會在main goroutine退出後退出,所以我們上面的代碼是有問題的,它不會列印出"hello". 因為main goroutine退出了,它沒有機會執行。我們需要用到WaitGroup在main goroutine上面等待它,如下代碼

var wg sync.WaitGroup
wg.Add(1)
go func() {
	defer wg.Done()
	fmt.Println("hello")
}()

wg.Wait()

wg.Add(1), 表示會執行一次, wg.Done就是說執行了一次。 wg.Wait()會等待add的一次done.

main goroutine 可以和 goroutine共用相同的地址空間執行,如下代碼

var wg sync.WaitGroup
salutation := "hello"
wg.Add(1)
go func() {
	defer wg.Done()
	salutation = "welcome"
}()

wg.Wait()
fmt.Println(salutation)

會列印出“welcome”, salutation變數在goroutine中被改變後,也會在main goroutine中生效。

我們來看下麵的代碼會輸出什麼

var wg sync.WaitGroup
for _, salutation := range []string{"hello", "greetings", "good day"} {
	wg.Add(1)
	go func() {
		defer wg.Done()
		mt.Println(salutation)
	}()
}
wg.Wait()

它會列印三個good day, 為什麼呢? 作者的解釋是在goroutine開始之前迴圈有很高的概率會退出,salutation的值不在範圍之內, go 語言運行時會足夠小心的將變數salutation值得引用仍然保留,由記憶體轉移到堆。 我不是特別明白作者得解釋,我自己理解下,感覺是for迴圈是main goroutine, 它執行for很快,調用goroutine得時候它已經迴圈完了,所以就拿到最後得值了。
這個我們想列印三個不同得值,使用下麵得代碼

var wg sync.WaitGroup
for _, salutation := range []string{"hello", "greetings", "good day"} {
	wg.Add(1)
	go func(value string) {
		defer wg.Done()
		fmt.Println(value)
	}(salutation)
}
wg.Wait()

這樣三個goroutine使用的是各自的副本。

goroutine的開銷是什麼樣的呢?

一個goroutine占多少記憶體? 作者書上說大概是2.817KB, 我自己實驗了下我的機器上是9.072KB,而OS線程的一般會是2M, 差距還是有些大,所以我們說啟動百萬的goroutine也是很正常的,而線程一般幾十個就不錯了。 下麵是示例代碼

func main() {
	memConsumed := func() uint64 {
		runtime.GC()
		var s runtime.MemStats
		runtime.ReadMemStats(&s)
		return s.Sys
	}

	var c <-chan interface{}
	var wg sync.WaitGroup
	noop := func() {
		wg.Done()
		<-c

	}

	const numGoroutines = 5e4
	wg.Add(numGoroutines)

	before := memConsumed()

	for i := numGoroutines; i > 0; i-- {
		go noop()
	}

	after := memConsumed()

	fmt.Printf("%.3fkb", float64(after-before)/numGoroutines/1000)
}

numGoroutines是我們想創建的goroutine數量
noop 這個方法一直等channel裡面的value,它不會退出,創建了的goroutine一直在記憶體中。
memConsumed 方法統計當前的記憶體, 我們在開始的時候統計下,在結束的時候統計下,相減後就得到消耗的記憶體。
作者還列舉了goroutine的上下文切換耗時225ns, 而線程切換1467ns, 相差也比較大,

最後

作者得出的結論是使用goroutine非常廉價


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 實現01 1.實現任務階段1 編寫mytomcat,該伺服器能給瀏覽器返回“你好,我是伺服器!”的簡單信息。 根據之前的tomcat框架整體分析,我們將瀏覽器發送請求,tomcat伺服器處理請求,返回資源的整個過程分為三個部分。現在來分析並初步實現第一部分的功能。 1.1基於socket開發服務端流 ...
  • 1.range # 1.range(起始值,結束值,步長) # 範圍 區間 # 步長不寫時預設是1 # 當裡面只有一個數據的時候,預設是0-結束值 # 當裡面有兩個數據的時候,是 起始值-結束值 print('1.range()') print(range(5, 9, 1)) print(type( ...
  • 生成器是一種特殊的迭代器,也可以說其父類型是迭代器 1、迭代器其實也有很多點要清楚,這裡先不做贅述 2、要清楚,迭代器調用iter()返回的是自身 1 def func(s, e): 2 """ 3 生成器函數 4 :param s:起始值 5 :param e: 末值 6 :return: 7 " ...
  • scanf在vs2022中是一個不安全的函數,vs自定義scanf_s是一個安全的函數,但是這在轉給其他編譯器可能不適用 我們可以在開頭加上一個#define _CRT_SECURE_NO_WARNINGS 1可以解決問題 但是自己打比較麻煩,這個時候我們可以打開vs編譯器的文件然後找到VC這個文件 ...
  • 平常是處理文字的時候更多用到的是字元串方面的工具類,作為學習漢字的工具,拼音還是很重要的一個輔助方式,分享一個漢字轉拼音的工具類。可以用於幫助學習漢字或者作為一些漢字的輔助說明都也是可以的。這個還支持將漢字拼音輸出為首字母,例如"愷龍"可以輸出為"kl",在現在大家很多時候都用縮寫的情況下,可以也可 ...
  • 1.HTTP是什麼? http是超文本傳輸協議用來在web瀏覽器和網站伺服器之間傳遞數據信息,http以明文的方式發送內容,不提供任何方式的數據加密,如果攻擊者截獲了Web瀏覽器和網站伺服器之間的傳輸報文,就可以直接讀懂其中的信息,因此,HTTP協議不適合傳輸一些敏感信息,比如:信用卡號、密碼等支付 ...
  • 1、使用註解需要導入的依賴 1、1在application.xml文件中加入該約束 xmlns:context=http://www.springframework.org/schema/context http://www.springframework.org/schema/context ht ...
  • 我國目前並未出台專門針對網路爬蟲技術的法律規範,但在司法實踐中,相關判決已屢見不鮮,K 哥特設了“K哥爬蟲普法”專欄,本欄目通過對真實案例的分析,旨在提高廣大爬蟲工程師的法律意識,知曉如何合法合規利用爬蟲技術,警鐘長鳴,做一個守法、護法、有原則的技術人員。 案情介紹 2018年1月至7月期間,咼某興 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...