清華尹成帶你實戰GO案例(1) Go 狀態協程
Go 狀態協程
在上面的例子中,我們演示瞭如何通過使用mutex來在多個協程之間共享狀態。另外一種方法是使用協程
內建的同步機制來實現。這種基於通道的方法和Go的通過訊息共享記憶體,保證每份資料為單獨的協程所有
的理念是一致的。
執行結果
ops: 880578
執行這個程式,我們會看到基於協程的狀態管理每秒可以處理800, 000個操作。對於這個例子來講,基於
協程的方法比基於mutex的方法更加複雜一點。當然在某些情況下還是很有用的。例如你有很多複雜的協
程,而且管理多個mutex可能導致錯誤。
在上面的例子中,我們演示瞭如何通過使用mutex來在多個協程之間共享狀態。另外一種方法是使用協程
內建的同步機制來實現。這種基於通道的方法和Go的通過訊息共享記憶體,保證每份資料為單獨的協程所有
的理念是一致的。
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
// 在這個例子中,將有一個單獨的協程擁有這個狀態。這樣可以
// 保證這個資料不會被並行訪問所破壞。為了讀寫這個狀態,其
// 他的協程將向這個協程傳送資訊並且相應地接受返回資訊。
// 這些`readOp`和`writeOp`結構體封裝了這些請求和回覆
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main() {
// 我們將計算我們執行了多少次操作
var ops int64 = 0
// reads和writes通道將被其他協程用來從中讀取或寫入資料
reads := make(chan *readOp)
writes := make(chan *writeOp)
// 這個是擁有`state`的協程,`state`是一個協程的私有map
// 變數。這個協程不斷地`select`通道`reads`和`writes`,
// 當有請求來臨的時候進行回覆。一旦有請求,首先執行所
// 請求的操作,然後給`resp`通道傳送一個表示請求成功的值。
go func() {
go func() {
var state = make(map[int]int)
for {
select {
case read := <-reads:
read.resp <- state[read.key]
case write := <-writes:
state[write.key] = write.val
write.resp <- true
}
}
}()
// 這裡啟動了100個協程來向擁有狀態的協程請求讀資料。
// 每次讀操作都需要建立一個`readOp`,然後傳送到`reads`
// 通道,然後等待接收請求回覆
for r := 0; r < 100; r++ {
go func() {
for {
read := &readOp{
key: rand.Intn(5),
resp: make(chan int)}
reads <- read
<-read.resp
atomic.AddInt64(&ops, 1)
}
}()
}
// 我們開啟10個寫協程
for w := 0; w < 10; w++ {
go func() {
for {
write := &writeOp{
key: rand.Intn(5),
val: rand.Intn(100),
resp: make(chan bool)}
writes <- write
<-write.resp
atomic.AddInt64(&ops, 1)
}
}()
}
// 讓協程執行1秒鐘
time.Sleep(time.Second)
// 最後輸出運算元量ops的值
opsFinal := atomic.LoadInt64(&ops)
fmt.Println("ops:", opsFinal)
}
執行結果
ops: 880578
執行這個程式,我們會看到基於協程的狀態管理每秒可以處理800, 000個操作。對於這個例子來講,基於
協程的方法比基於mutex的方法更加複雜一點。當然在某些情況下還是很有用的。例如你有很多複雜的協
程,而且管理多個mutex可能導致錯誤。
當然你可以選擇使用任意一種方法,只要你保證這種方法讓你覺得很舒服而且也能保證程式的正確性。
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- 清華尹成帶你實戰GO案例(28)Go 方法Go
- 清華尹成帶你實戰GO案例(35)Go 互斥Go
- 清華尹成帶你實戰GO案例(38)Go 介面Go
- 清華尹成帶你實戰GO案例(46)Go 排序Go排序
- 清華尹成帶你實戰GO案例(47)Go 切片Go
- 清華尹成帶你實戰GO案例(2) Go 字典Go
- 清華尹成帶你實戰GO案例(7)Go DeferGo
- 清華尹成帶你實戰GO案例(7)Go ExitGo
- 清華尹成帶你實戰GO案例(12)Go PanicGo
- 清華尹成帶你實戰GO案例(22)Go常量Go
- 清華尹成帶你實戰GO案例(29)Go 工作池Go
- 清華尹成帶你實戰GO案例(37)Go 集合功能Go
- 清華尹成帶你實戰GO案例(49)Go 時間Go
- 清華尹成帶你實戰GO案例(52)Go數值Go
- 清華尹成帶你實戰GO案例(54)Go 陣列Go陣列
- 清華尹成帶你實戰GO案例(57)Go通道方向Go
- 清華尹成帶你實戰GO案例(63)Go 指標Go指標
- 清華尹成帶你實戰GO案例(8)Go for迴圈Go
- 清華尹成帶你實戰GO案例(10)Go JSON支援GoJSON
- 清華尹成帶你實戰GO案例(11)Go Line FiltersGoFilter
- 清華尹成帶你實戰GO案例(17) Go URL解析Go
- 清華尹成帶你實戰GO案例(19)Go變數Go變數
- 清華尹成帶你實戰GO案例(23)Go 超時Go
- 清華尹成帶你實戰GO案例(14)Go SHA1 雜湊Go
- 清華尹成帶你實戰GO案例(30)Go 關閉通道Go
- 清華尹成帶你實戰GO案例(39)Go 結構體Go結構體
- 清華尹成帶你實戰GO案例(40)Go 程式觸發Go
- 清華尹成帶你實戰GO案例(41)Go 程式執行Go
- 清華尹成帶你實戰GO案例(50)Go 時間戳Go時間戳
- 清華尹成帶你實戰GO案例(53)Go 數字解析Go
- 清華尹成帶你實戰GO案例(55)Go 隨機數Go隨機
- 清華尹成帶你實戰GO案例(58)Go通道緩衝Go
- 清華尹成帶你實戰GO案例(5)Go 自定義排序Go排序
- 清華尹成帶你實戰GO案例(13)Go range函式Go函式
- 清華尹成帶你實戰GO案例(16)Go Switch語句Go
- 清華尹成帶你實戰GO案例(20)Go 遍歷通道Go
- 清華尹成帶你實戰GO案例(25)Go 打點器Go
- 清華尹成帶你實戰GO案例(27)Go 讀取檔案Go