golang読み書きロックはスレッドの安全を保証する
いつ鍵を使う必要がありますか?
反発ロック
反発ロックは共有リソースへのアクセスを制御する一般的な方法であり、同時に1つの反発ロックだけが共有リソースへのアクセスを制御する一般的な方法であることを保証し、同時に1つのgoroutineだけが共有リソースにアクセスできることを保証することができる(同じ時点で1つのスレッドだけがロックを取得できる)
まず、マルチスレッドがグローバル変数に同時にアクセスした場合、結果はどうなるかを、同時読み書きの例で示します.package main
import ("fmt")
var count int
func main() {
for i := 0; i < 2; i++ {
go func() {
for i := 1000000; i > 0; i-- {
count ++
}
fmt.Println(count)
}()
}
fmt.Scanf("
") //
}
:
980117
1011352 // :200000
コードを修正し、累積した場所に反発ロックを追加すると、毎回得られる結果が所望の値であることが保証されます.package main
import ("fmt"
"sync"
)
var (
count int
lock sync.Mutex
)
func main() {
for i := 0; i < 2; i++ {
go func() {
for i := 1000000; i > 0; i-- {
lock.Lock()
count ++
lock.Unlock()
}
fmt.Println(count)
}()
}
fmt.Scanf("
") //
}
:
1952533
2000000 //
読み書きロック(sync.RWMutex)
読み書きが少ない環境では、反発ロックよりも効率的に読み書き反発ロック(sync.RWMutex)を優先的に使用できます.syncパッケージのRWMutexは、読み書き反発ロックのパッケージを提供します.
リード・ライト・ロックには、リード・ロックとライト・ロックがあります.
反発ロックは共有リソースへのアクセスを制御する一般的な方法であり、同時に1つの反発ロックだけが共有リソースへのアクセスを制御する一般的な方法であることを保証し、同時に1つのgoroutineだけが共有リソースにアクセスできることを保証することができる(同じ時点で1つのスレッドだけがロックを取得できる)
まず、マルチスレッドがグローバル変数に同時にアクセスした場合、結果はどうなるかを、同時読み書きの例で示します.
package main
import ("fmt")
var count int
func main() {
for i := 0; i < 2; i++ {
go func() {
for i := 1000000; i > 0; i-- {
count ++
}
fmt.Println(count)
}()
}
fmt.Scanf("
") //
}
:
980117
1011352 // :200000
コードを修正し、累積した場所に反発ロックを追加すると、毎回得られる結果が所望の値であることが保証されます.
package main
import ("fmt"
"sync"
)
var (
count int
lock sync.Mutex
)
func main() {
for i := 0; i < 2; i++ {
go func() {
for i := 1000000; i > 0; i-- {
lock.Lock()
count ++
lock.Unlock()
}
fmt.Println(count)
}()
}
fmt.Scanf("
") //
}
:
1952533
2000000 //
読み書きロック(sync.RWMutex)
読み書きが少ない環境では、反発ロックよりも効率的に読み書き反発ロック(sync.RWMutex)を優先的に使用できます.syncパッケージのRWMutexは、読み書き反発ロックのパッケージを提供します.
リード・ライト・ロックには、リード・ロックとライト・ロックがあります.
書き込みロックを設定することで、データの一貫性を実現できます.
package main
import ("fmt"
"sync"
)
var (
count int
rwLock sync.RWMutex
)
func main() {
for i := 0; i < 2; i++ {
go func() {
for i := 1000000; i > 0; i-- {
rwLock.Lock()
count ++
rwLock.Unlock()
}
fmt.Println(count)
}()
}
fmt.Scanf("
") //
}
:
1968637
2000000