對於併發這個概念,我想大家都對它不會陌生,今天就從簡單的火車站賣票問題出發,來談談併發。
首先宣告本文的**是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 語言的執行緒是併發機制,不是並行機制。那麼,什麼是併發,什麼是並行?併發是不同的 塊交替執行,也就是交替可以做不同的事情。並行是不同的 塊同時執行,也就是同時可以做不同的事情。舉個生活化場景的例子 你正在家看書,忽然 來了,然後你接 通話完成後繼續看書,這就是併發,看書和接 交替做。如果 來了...