golang 閒談併發

2021-07-25 13:46:01 字數 1924 閱讀 5349

對於併發這個概念,我想大家都對它不會陌生,今天就從簡單的火車站賣票問題出發,來談談併發。

首先宣告本文的**是golang(因為最近開始用的就是golang),對於其他的語言其實也是相通的,那麼正式開始正題吧,首先我們來看看,賣一張票,總票數就減一,一般來說我們會這麼寫:

package main

import (

「fmt」

「math/rand」

"time"
)

var totle_tickets int = 1000

func sell_tickets() else

} }

func main()

執行耗時大概1-2秒,那麼,我們來試試用協程加鎖的方式:

// bingfa_anquan project main.go

package main

import (

「fmt」

「math/rand」

「runtime」

「sync」

「time」

) var totle_tickets int = 1000

var ch chan bool

var mutex sync.mutex

func sell_tickets(i int) else

} }

func main()

for i := 0; i < 10; i++

t2 := time.since(t)

fmt.println(t2)

} 執行結果:耗時大概5秒多!很奇怪是不是,為什麼協程執行卻耗時更久了。下面我們來分析分析:

第乙個程式:

main函式呼叫賣票函式,將1000張票賣完

第二個程式:

main函式中建立5個協程,將1000張票賣完

按照這個邏輯乙個人賣票肯定是沒有5個人賣票快的,但是這有個問題,那就是協程都是在操作tickets這個變數,而且該變數加鎖了,那麼這就意味著任意乙個協程中,只要我在操作賣票這個操作,那麼其他協程是不能去操作這個變數的,這樣一來就變成哪個協程」運氣好」輪到他,同時票已經沒有鎖定的時候,他才可以賣票,這個執行的時間=建立協程的時間+協程賣票的時間+通知主線程(票已經賣完了,可以結束了),所以時間反而變長了。

那麼現在我們來思考下,如果開協程反而更慢了,那為什麼還說多執行緒(協程)處理比單執行緒快呢?根源就在於這個例子有個不合理的地方,那就是事務並不複雜,同時協程(不管建立了多少個)等待條件不合理。一般來說,我們在使用協程處理伺服器端的事務的時候,都會有很多操作,有些協程處理完自己的任務就把結果發走了,並不需要等待,有些協程等其他協程把結果給過來,一拿到就處理,處理完又把結果發走,也就是說大家(協程)做著自己的工作,並沒有出現大家都要操作乙個物件(變數),所有人都要等別人unlock的情況。

語言組織不是很好,但是感覺已經把想要表達的說清楚了,並不是所有的情況都適合併發,適合併發的情況可能是下面這樣(舉乙個栗子幫助理解):

這裡**部分需要說明下,有些人可能會說,才1000張票就用併發,完全就是沒意義,但是我這裡只是舉個例子,讀者可以自己吧上面**修改為一千萬或是乙個億,但是,程式執行時間太長,沒意義。這裡讀者可以把第二個程式加鎖**去掉,然後修改票數為一千萬張你會發現,第二個程式執行的時間比第乙個快大約10倍,協程開100個,執行速度就比第乙個快大概100倍!但是結果會出現你所不希望看到的(自己執行看看)。

golang 併發實踐

golang 高併發主要是依靠sync包下的api實現,首先就是waitgroup 先說說waitgroup的用途 它能夠一直等到所有的goroutine執行完成,並且阻塞主線程的執行,直到所有的goroutine執行完成。waitgroup總共有三個方法 add delta int done wa...

GoLang 併發小結

006.併發 1 概念 1.1 goroutine是go並行設計的核心,goroutine的本質是輕量級執行緒 1.2 golang的runtime實現了對輕量級執行緒即goroutine的智慧型排程管理 1.3 p m g原理 1.3.1 runtime有p m g三個概念,p對應作業系統程序 對...

golang 併發 並行

go 語言的執行緒是併發機制,不是並行機制。那麼,什麼是併發,什麼是並行?併發是不同的 塊交替執行,也就是交替可以做不同的事情。並行是不同的 塊同時執行,也就是同時可以做不同的事情。舉個生活化場景的例子 你正在家看書,忽然 來了,然後你接 通話完成後繼續看書,這就是併發,看書和接 交替做。如果 來了...