bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

go語言啟用線程 golang開啟線程

為什么go語言適合開發網游服務器端

個人覺得golang十分適合進行網游服務器端開發,寫下這篇文章總結一下。 從網游的角度看: 要成功的運營一款網游,很大程度上依賴于玩家自發形成的社區。只有玩家自發形成一個穩定的生態系統,游戲才能持續下去,避免鬼城的出現。而這就需要多次大量導入用戶,在同時在線用戶量達到某個臨界點的時候,才有可能完成。因此,多人同時在線十分有必要。 再來看網游的常見玩法,除了排行榜這類統計和數據匯總的功能外,基本沒有需要大量CPU時間的應用。以前的項目里,即時戰斗產生的各種傷害計算對CPU的消耗也不大。玩家要完成一次操作,需要通過客戶端-服務器端-客戶端這樣一個來回,為了獲得高響應速度,滿足玩家體驗,服務器端的處理也不能占用太多時間。所以,每次請求對應的CPU占用是比較小的。 網游的IO主要分兩個方面,一個是網絡IO,一個是磁盤IO。網絡IO方面,可以分成美術資源的IO和游戲邏輯指令的IO,這里主要分析游戲邏輯的IO。游戲邏輯的IO跟CPU占用的情況相似,每次請求的字節數很小,但由于多人同時在線,因此并發數相當高。另外,地圖信息的廣播也會帶來比較頻繁的網絡通信。磁盤IO方面,主要是游戲數據的保存。采用不同的數據庫,會有比較大的區別。以前的項目里,就經歷了從MySQL轉向MongoDB這種內存數據庫的過程,磁盤IO不再是瓶頸。總體來說,還是用內存做一級緩沖,避免大量小數據塊讀寫的方案。 針對網游的這些特點,golang的語言特性十分適合開發游戲服務器端。 首先,go語言提供goroutine機制作為原生的并發機制。每個goroutine所需的內存很少,實際應用中可以啟動大量的goroutine對并發連接進行響應。goroutine與gevent中的greenlet很相像,遇到IO阻塞的時候,調度器就會自動切換到另一個goroutine執行,保證CPU不會因為IO而發生等待。而goroutine與gevent相比,沒有了python底層的GIL限制,就不需要利用多進程來榨取多核機器的性能了。通過設置最大線程數,可以控制go所啟動的線程,每個線程執行一個goroutine,讓CPU滿負載運行。 同時,go語言為goroutine提供了獨到的通信機制channel。channel發生讀寫的時候,也會掛起當前操作channel的goroutine,是一種同步阻塞通信。這樣既達到了通信的目的,又實現同步,用CSP模型的觀點看,并發模型就是通過一組進程和進程間的事件觸發解決任務的。雖然說,主流的編程語言之間,只要是圖靈完備的,他們就都能實現相同的功能。但go語言提供的這種協程間通信機制,十分優雅地揭示了協程通信的本質,避免了以往鎖的顯式使用帶給程序員的心理負擔,確是一大優勢。進行網游開發的程序員,可以將游戲邏輯按照單線程阻塞式的寫,不需要額外考慮線程調度的問題,以及線程間數據依賴的問題。因為,線程間的channel通信,已經表達了線程間的數據依賴關系了,而go的調度器會給予妥善的處理。 另外,go語言提供的gc機制,以及對指針的保護式使用,可以大大減輕程序員的開發壓力,提高開發效率。 展望未來,我期待go語言社區能夠提供更多的goroutine間的隔離機制。個人十分推崇erlang社區的脆崩哲學,推動應用發生預期外行為時,盡早崩潰,再fork出新進程處理新的請求。對于協程機制,需要由程序員保證執行的函數不會發生死循環,導致線程卡死。

創新互聯主營乳山網站建設的網絡公司,主營網站建設方案,重慶APP開發,乳山h5微信小程序開發搭建,乳山網站營銷推廣歡迎乳山等地區企業咨詢

go語言語法(基礎語法篇)

import "workname/packetfolder"

導入多個包

方法調用 包名.函數//不是函數或結構體所處文件或文件夾名

packagename.Func()

前面加個點表示省略調用,那么調用該模塊里面的函數,可以不用寫模塊名稱了:

當導入一個包時,該包下的文件里所有init()函數都會被執行,然而,有些時候我們并不需要把整個包都導入進來,僅僅是是希望它執行init()函數而已。下劃線的作用僅僅是為了調用init()函數,所以無法通過包名來調用包中的其他函數

import _ package

變量聲明必須要使用否則會報錯。

全局變量運行聲明但不使用。

func 函數名 (參數1,參數2,...) (返回值a 類型a, 返回值b 類型b,...)

func 函數名 (參數1,參數2,...) (返回值類型1, 返回值類型2,...)

func (this *結構體名) 函數名(參數 string) (返回值類型1, 返回值類型2){}

使用大小來區分函數可見性

大寫是public類型

小寫是private類型

func prifunc int{}

func pubfunc int{}

聲明靜態變量

const value int

定義變量

var value int

聲明一般類型、接口和結構體

聲明函數

func function () int{}

go里面所有的空值對應如下

通道類型

內建函數 new 用來分配內存,它的第一個參數是一個類型,不是一個值,它的返回值是一個指向新分配類型零值的指針

func new(Type) *Type

[這位博主有非常詳細的分析]

Go 語言支持并發,我們只需要通過 go 關鍵字來開啟 goroutine 即可。

goroutine 是輕量級線程,goroutine 的調度是由 Golang 運行時進行管理的。

同一個程序中的所有 goroutine 共享同一個地址空間。

語法格式如下:

通道(channel)是用來傳遞數據的一個數據結構。

通道的聲明

通道可用于兩個 goroutine 之間通過傳遞一個指定類型的值來同步運行和通訊。操作符 - 用于指定通道的方向,發送或接收。如果未指定方向,則為雙向通道。

[這里有比較詳細的用例]

go里面的空接口可以指代任何類型(無論是變量還是函數)

聲明空接口

go里面的的強制類型轉換語法為:

int(data)

如果是接口類型的強制轉成其他類型的語法為:

go里面的強制轉換是將值復制過去,所以在數據量的時候有比較高的運行代價

Golang的調度模型

Go有四大核心模塊,基本全部體現在runtime,有調度系統、GC、goroutine、channel,那么深入理解其中的精髓可以幫助我們理解Go這一門語言!

參考: 調度系統設計精要

下面是我用Go語言簡單寫的一個調度器,大家可以看看設計思路,以及存在的問題!

1、測試條件,調度器只啟動兩個線程,然后一個線程主要是負責循環的添加任務,一個線程循環的去執行任務

2、測試條件,調度器啟動三個線程,然后兩個線程去執行任務,一個添加任務

3、繼續測試,啟動十個線程,一個添加任務,九個執行任務

4、我們添加一些阻塞的任務

執行可以看到完全不可用

1、 可以看到隨著M的不斷的增加,可以發現執行任務的數量也不斷的減少,原因是什么呢?有興趣的同學可以加一個pprof可以看看,其實大量的在等待鎖的過程!

2、如果我的M運行了類似于Sleep操作的方法如何解決了,我的調度器還能支撐這個量級的調度嗎?

關于pprof如何使用:在代碼頭部加一個這個代碼:

我們查看一下 go tool pprof main/prof.pporf

可以看到真正執行代碼的時間只有 0.17s + 0.02s 其他時間都被阻塞掉了!

1、GM模型中的所有G都是放入到一個queue,那么導致所有的M取執行任務時都會去競爭鎖,我們插入G也會去競爭鎖,所以解決這種問題一般就是減少對單一資源的競爭,那就是桶化,其實就是每個線程都分配一個隊列

2、GM模型中沒有任務狀態,只有runnable,假如任務遇到阻塞,完全可以把任務掛起再喚醒

這里其實會遇到一個問題,假如要分配很多個線程,那么此時隨著線程的增加,也會造成隊列的增加,其實也會造成調度器的壓力,因為它需要遍歷全部線程的隊列去分配任務以及后續會講到的竊取任務!

因為我們知道CPU的最大并行度其實取決于CPU的核數,也就是我們沒必要為每個線程都去分配一個隊列,因為就算是給他們分配了,他們自己去那執行調度,其實也會出現大量阻塞,原因就是CPU調度不過來這些線程!

Go里面是只分配了CPU個數的隊列,這里就是P這個概念,你可以理解為P其實是真正的資源分配器,M很輕只是執行程序,所有的資源內存都維護在P上!M只有綁定P才能執行任務(強制的)!

這樣做的好處:

1、首先調度程序其實就是調度不同狀態的任務,go里面為Go標記了不同的狀態,其實大概就是分為:runnable,running,block等,所以如何充分調度不同狀態的G成了問題,那么關于阻塞的G如何解決,其實可以很好的解決G調度的問題!

上面這些情況其實就分為:

2、用戶態阻塞,一般Go里面依靠 gopark 函數去實現,大體的代碼邏輯基本上和go的調度綁定死了

源碼在:

3、其實對于netpool 這種nio模型,其實內核調用是非阻塞的,所以go開辟了一個網絡輪訓器隊列,來存放這些被阻塞的g,等待內核被喚醒!那么什么時候會被喚醒了,其實就是需要等待調度器去調度了!

4、如果是內核態阻塞了(內核態阻塞一般都會將線程掛起,線程需要等待被喚醒),我們此時P只能放棄此線程的權利,然后再找一個新的線程去運行P!

關于著新線程:找有沒有idle的線程,沒有就會創建一個新的線程!

關于當內核被喚醒后的操作:因為GPM模型所以需要找到個P綁定,所以G會去嘗試找一個可用的P,如果沒有可用的P,G會標記為runnable放到全局隊列中!

5、其實了解上面大致其實就了解了Go的基本調度模型

答案文章里慢慢品味!

如果某個 G 執行時間過長,其他的 G 如何才能被正常的調度? 這便涉及到有關調度的兩個理念:協作式調度與搶占式調度。協作式和搶占式這兩個理念解釋起來很簡單: 協作式調度依靠被調度方主動棄權;搶占式調度則依靠調度器強制將被調度方被動中斷。

例如下面的代碼,我本地的版本是 go1.13.5

執行: GOMAXPROCS=1 配置全局只能有一個P

可以看到main函數無法執行!也就是那個go 空轉搶占了整個程序

備注:

但是假如我換為用 1.14+版本執行,有興趣的話可以使用我的docker鏡像,直接可以拉?。? fanhaodong/golang:1.15.11 和 fanhaodong/golang:1.13.5

首先我們知道G/M/P,G可能和M也可能和P解除綁定,那么關于數據變量放在哪哇!其實這個就是逃逸分析!

輸出可以看到其實沒有發生逃逸,那是因為 demo被拷貝它自己的??臻g內

備注:

-gcflags"-N -l -m" 其中 -N禁用優化-l禁止內聯優化,-m打印逃逸信息

那么繼續改成這個

可以看到發現 demo對象其實被逃逸到了堆上!這就是不會出現類似于G如果被別的M執行,其實不會出現內存分配位置的問題!

所以可以看到demo其實是copy到了堆上!這就是g逃逸的問題,和for循環一樣的

執行可以發現,其實x已經逃逸到了堆上,所以你所有的g都引用的一個對象,如何解決了

如何解決了,其實很簡單

也談goroutine調度器

圖解Go運行時調度器

Go語言回顧:從Go 1.0到Go 1.13

Go語言原本

調度系統設計精要

Scalable Go Scheduler Design Doc

分享題目:go語言啟用線程 golang開啟線程
網站URL:http://vcdvsql.cn/article26/dopescg.html

成都網站建設公司_創新互聯,為您提供Google軟件開發網站設計公司商城網站、網站策劃、網站設計

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

外貿網站建設