Go併發程式設計--基於channel訊號量來實現互斥鎖
阿新 • • 發佈:2019-02-09
概述
根據前面的一片文章:《Go併發程式設計–通過channel來實現訊號量原語》我們實現了訊號量的基本原語P和V操作,本章介紹如何通過P操作和V操作來實現互斥鎖。
實現原理
當我們把channel的容量設定為1時,P和V操作就變成了,lock和unlock操作。為什麼呢?我們來看下程式碼實現:
/* mutexes */
func (s semaphore) Lock() {
s.P(1)
}
func (s semaphore) Unlock() {
s.V(1)
}
上篇講過P和V操作的實現,當channel的容量只有一個,此時P和V的數量變為1時,進行P操作的協程只能有一個,在該協程執行完P操作沒有執行V操作時,其他協程只能等待,這樣就實現了只能有一個協程訪問臨界區的功能。
完整程式碼
package main
import (
"fmt"
"os"
"time"
)
type Empty interface {}
type semaphore chan Empty
// 實現訊號量原語
// acquire n resources
func (s semaphore) P(n int) {
e := new(Empty)
for i := 0; i < n; i++ {
s <- e
}
}
// release n resources
func (s semaphore) V(n int ) {
for i := 0; i < n; i++ {
<-s
}
}
// 通過以上原語實現互斥鎖
/* mutexes */
func (s semaphore) Lock() {
s.P(1)
}
func (s semaphore) Unlock() {
s.V(1)
}
// 工作協程,這裡只是列印0-99的整數
func printInt(sem semaphore) {
sem.Lock()
for i := 0; i < 100; i++ {
fmt.Fprintf(os.Stderr, "%d\n" , i)
}
sem.Unlock()
}
func main() {
sem := make(semaphore, 1)
go printInt(sem)
go printInt(sem)
// 等待兩個goroutine結束
time.Sleep(10e9)
fmt.Fprintf(os.Stderr, "end\n")
}
當channel容量時1是,就只能有一個協程能完成P操作,直到該協程完成了V操作,其他協程才能進行P操作,這樣就實現了互斥鎖。
總結
通過channel實現的訊號量原語,我們實現了互斥鎖。通過P和V原語我們還能實現訊號量的一些操作,從而更好的控制協程間的通訊。如何實現訊號量操作,請繼續看後面的文章。