學習過作業系統的都知道程式有臨界區這個概念,臨界區就是程式片段訪問臨界資源的那部分**,臨界區同一時刻只能有乙個執行緒進行訪問,其他執行緒需要訪問的話必須等待資源空閒。那麼一般程式語言都會使用鎖來進行臨界區訪問控制。
golang主要有兩種鎖:互斥鎖和讀寫鎖
互斥鎖mutex:
mutex 用於提供一種加鎖機制(locking mechanism),保證同一時刻只有乙個goroutine在臨界區執行。
互斥鎖定義如下:
var mutex sync.mutex;
它用於對goroutine進行加鎖和解鎖,lock()之後其他goroutine便不能對其鎖定的區進行操作。
看下面**:
package main
import (
"fmt"
"time"
)func main() ()
time.sleep(time.second)
fmt.println(x)
}
一般它都會列印1。
但是有沒有這種可能:
併發執行過程**現時間延誤,例如我goroutine1執行完後x=1,goroutine2拿到的x並不是0,而是goroutine1已經執行好的x = 1,那麼x再次自加,就會返回2。
這就是由於多個goroutine對x進行操作之後可能產生的錯誤,沒有進行臨界區訪問控制。
加鎖:
package main
import (
"fmt"
"sync"
"time"
)func main() ()
time.sleep(time.second)
fmt.println(x)
}
這樣的話就是執行緒安全了,只有乙個goroutine對x進行操作。
讀寫鎖rwmutex:
讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於自旋鎖而言,能提高併發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實際的邏輯cpu數。寫者是排他性的,乙個讀寫鎖同時只能有乙個寫者或多個讀者(與cpu數相關),但不能同時既有讀者又有寫者。
總的來說,就是寫的時候不允許讀和多個寫,讀的時候不允許寫但是允許多個讀,讀和寫不能同時進行。
func (*rwmutex) lock
func (*rwmutex) unlock
func (*rwmutex) rlock
func (*rwmutex) runlock
lock方法將rw鎖定為寫入狀態,禁止其他執行緒讀取或者寫入。
unlock方法解除rw的寫入鎖狀態,如果m未加寫入鎖會導致執行時錯誤。
rlock方法將rw鎖定為讀取狀態,禁止其他執行緒寫入,但不禁止讀取。
runlock方法解除rw的讀取鎖狀態,如果m未加讀取鎖會導致執行時錯誤。
func read()
func write()
func main() ()
time.sleep(2 * time.second)
}
執行結果: golang的goroutine 同步 鎖
goroutine 協程 程序 執行緒?程序,執行緒都是os層面的系統排程方式。協程是使用者層面的呼叫方式,利用更少的資源進行切換,而不需要system call。但協程是呼叫的os的執行緒在執行。當乙個函式為def abc 時,使用go abc 即為開乙個協程去呼叫這個函式 goroutine在遇...
golang 併發鎖的陷阱
package main import sync strconv fmt type node struct var cache node func main cache 1 node wg sync.waitgroup for i 0 i 10000 i i wg.wait fmt.println ...
golang 自旋鎖的實現
cas演算法 compare and swap cas演算法是一種有名的無鎖演算法。無鎖程式設計,即不使用鎖的情況下實現多執行緒之間的變數同步,也就是在沒有執行緒被阻塞的情況下實現變數的同步,所以也叫非阻塞同步 non blocking synchronization cas演算法涉及到三個運算元 ...