假如我們沒有用協程通道或者加鎖的方式,直接併發使用map,會出現線性不安全
例如:
package main報錯:import (
"time"
"fmt"
)var tmap map[int]int
func main()
time.sleep(1e10)
fmt.println("--------------map = ", len(tmap))
}func putmap(i int)
解決方法:
使用鎖之後就不會有問題:
package main又或者是利用協程通道,來保證執行緒安全import (
"time"
"fmt"
"sync"
)var tmap map[int]int
var mutex sync.mutex
func main()
time.sleep(1e10)
fmt.println("--------------map = ", len(tmap))
}func putmap(i int)
package maingo的哲學之一就是:import (
"time"
"fmt"
)var tmap map[int]int
func main()
time.sleep(1e10)
fmt.println("--------------map = ", len(tmap))
}func putmap(data chan int, i int)
func goroutine(data chan int)
}
不要通過共享記憶體來通訊,而要通過通訊來共享記憶體
,前者就是傳統的加鎖
,後者就是channel。
反正涉及到併發安全性的資料結構,盡量使用協程通道:傳送乙個資料到channel 和 從channel接收乙個資料 都是 原子性的。
可以認為加鎖的map就是erlang裡面的ets,而使用協程通道就是erlang裡面的程序裡的資料結構
最後我們來看一下go對redis的併發操作:
package main也沒任何問題!!!import (
"time"
"slg_game_server/server/goredis"
"slg_game_server/server/util"
)func main()
time.sleep(1e10)
}func putredis(i int)
因為redis服務端是個單執行緒的架構,不同的client雖然看似可以同時保持連線,但發出去的命令在伺服器看來是序列化執行的,
因此對服務端來說,並不存在併發問題!!!
Golang協程與通道整理
協程goroutine 不由os排程,而是使用者層自行釋放cpu,從而在執行體之間切換。go在底層進行協助實現 涉及系統呼叫的地方由go標準庫協助釋放cpu 總之,不通過os進行切換,自行切換,系統執行開支大大降低 通道channel 併發程式設計的關鍵在於執行體之間的通訊,go通過通過channe...
Golang協程與通道整理
協程goroutine 不由os排程,而是使用者層自行釋放cpu,從而在執行體之間切換。go在底層進行協助實現 涉及系統呼叫的地方由go標準庫協助釋放cpu 總之,不通過os進行切換,自行切換,系統執行開支大大降低 通道channel 併發程式設計的關鍵在於執行體之間的通訊,go通過通過channe...
Go 協程 通道
目錄 go 協程 go 通道 go 協程go 協程可以看作是輕量級執行緒。與執行緒相比,建立乙個go協程的成本很小。因此在go應用中,常常會看到有數以千計的go協程併發地執行 go 協程相比於執行緒的優勢 啟動乙個go協程 在呼叫函式和方法時,在前面加上關鍵字go,可以讓乙個新的go協程併發執行 p...