我就廢話不多說了,大家還是直接看**吧~
package main
import "fmt"
import "sy程式設計客棧nc"
var ch = make(chan int)
func do(lock *sync.mutex, ct *int)
//通過全域性的 map 來通訊
var (
sum )
func calc(t *task)
fmt.printf("%d! = %v\n", t.程式設計客棧n, sum)
lock.lock()
sum++
lock.unlock() }
func main()
go calc(t) }
time.sleep(5 * time.second)
lock.lock()
// for k, v := range m
lock.unlock()
}單純地將函式併發執行是沒有意義的。函式與函式間需要交換資料才能體現程式設計客棧併發執行函式的意義。雖然可以使用共享記憶體進行資料交換,但是共享記憶體在不同的 goroutine 中容易發生競態問題。為了保證資料交換的正確性,必須使用互斥量對記憶體進行加鎖,這種做法勢必造成效能問題。
go 語言提倡使用通訊的方法代替共享記憶體,這裡通訊的方法就是使用通道(channel)
channel 具有幾個特性:
1.類似unix中的管道(pipe)
2.先進先出
3.執行緒安全,多個goroutine同時訪問,不需要加鎖
4.channel是有型別的,乙個整數的channel 只能存放整
2.1使用通道傳送資料
通道建立後,就可以使用通道進行傳送和接收操作。
1) 通道傳送資料的格式
通道的傳送使用特殊的操作符
通道變數
通道變數:通過make建立好的通道例項。
值:可以是變數、常量、表示式或者函式返回值等。值的型別必須與ch通道的元素型別一致。
2) 通過通道傳送資料的例子
使用 make 建立乙個通道後,就可以使用
// 建立乙個空介面通道
ch := make(chan inte***ce{})
// 將0放入通道中
ch2.2 使用通道接收資料
1)通道接收同樣使用
① 通道的收發操作在不同的兩個 goroutine 間進行。
由於通道的資料在沒有接收方處理時,資料傳送方會持續阻塞,因此通道的接收必定在另外乙個 goroutine 中進行。
② 接收將持續阻塞直到傳送方傳送資料。
如果接收方接收時,通道中沒有傳送方傳送資料,接收方也會發生阻塞,直到傳送方傳送資料為止
③ 每次接收乙個元素。
通道一次只能接收乙個資料元素。
通道的資料接收一共有以下 4 種寫法。
2) 阻塞接收資料
阻塞模式接收資料時,將接收變數作為
data :=
執行該語句時將會阻塞,直到接收到資料並賦值給 data 變數。
3) 非阻塞接收資料
使用非阻塞方式從通道接收資料時,語句不會發生阻塞,格式如下:
data, ok :=
data:表示接收到的資料。未接收到資料時,data 為通道型別的零值。
ok:表示是否接收到資料。
非阻塞的通道接收方法可能造成高的 cpu 占用,因此使用非常少。如果需要實現接收超時檢測,可以配合 select 和計時器 channel 進行,可以參見後面的內容。
4) 接收任意資料,忽略接收的資料
阻塞接收資料後,忽略從通道返回的資料,格式如下:
執行該語句時將會發生阻塞,直到接收到資料,但接收到的資料會被忽略。這個方式實際上只是通過通道在 goroutine 間阻塞收發實現併發
2.3 發生阻塞的2種情況
1)傳送方傳送阻塞:在通道資料沒有接收方處理時,通道的資料一開始會存放到固定的資料緩衝區內,超出緩衝區的大小將發生持續阻塞。
package main
func main() {
var ch chan int
ch = make(chan int, 5) //定義資料快取區設定為5個大小
//將資料儲存在緩衝區內並不會發生當前執行緒阻塞
for i := 0; i < 5; i++ {
ch這個程式的執行結果直接painc 因為在管道加入ch
2) 資料接收方發生阻塞:如果接收方沒有接收到資料,接收方等待傳送方傳送資料,等待的過程也會使資料接收的協程發生阻塞。
package main
import (
"fmt"
"time")
func main() {
var ch chan int
ch = make(chan int) //無定義資料快取區
go func() {
var a =
這個程式的執行結果是延時4秒後控制台列印出通道的值1,5秒後主程式結束。上邊的程式是先讓接收者協程開啟等待接收通道的值,而傳送者是主函式延遲4秒後才將值放入通道ch,匿名函式中不得不等待傳送者的值,所以造成了匿名併發函式的阻塞。 我們可以思考到,如果去掉4秒等待的時間, 這個程式就是使用channel作為協程之間同步的最簡單的例子,我們發現channel同步的特性就是無資料快取區。
同樣乙個程式,當你把接受者 go func() 程式放到 ch
package main
import (
"fmt"
"time")
func main() {
var ch chan int
ch = make(chan int) //無定義資料快取區
* 4) //主線程等待4才給管道資料
ch本文標題: go 協程返回值處理操作
本文位址:
Flex TitleWindow返回值處理
flex有2 中彈出視窗 alert.show 和通過 popupmanager 產生出來的彈出視窗,其中 alert 我們可以稱之為彈出對話方塊主要用於資訊提示,而用 popupmanager 產生出來的彈出視窗才是本文需要討論的議題。1 彈出視窗如何彈出 移除 利用 popupmanager 可...
Flex TitleWindow返回值處理
flex 有2中彈出視窗 alert.show 和通過 popupmanager產生出來的彈出視窗,其中alert我們可以稱之為彈出對話方塊主要用於資訊提示,而用popupmanager產生出來的彈出視窗才是本文需要討論的議題。1 彈出視窗如何彈出 移除 利用popupmanager,可用popup...
Mybatis Update操作返回值
後端的資料持久化使用的是 mybatis 在做高併發下賬戶增減餘額的時候,打算使用樂觀鎖來解決這個問題。在獲取update操作的返回值時遇到了乙個問題,似乎 mybatis 進行 update 操作得到的 int 返回值並不是影響的行數。這下就尷尬了。資料庫連線配置為 接來下,我們來編寫乙個簡單的單...