比如一個簡單的 int 變數,在不對這個變數加鎖的情況下僅使用 CompareAndSwap 是如何實現原子操作的?
因為可能 2 個執行緒同時拿到了這個變數,那麼如果這時 2 個執行緒幾乎是同時 compare 的時候可能就是同時為 true。
那麼底層是否其實是存在類似鎖的實現呢?
舉個 Go 中協程的例子:
package main
import (
"fmt"
"sync"
"sync/atomic"
)
var counter int32 = 0
func main() {
n := 100
wg := new(sync.WaitGroup)
wg.Add(n)
for i:=0; i <n; i++ {
go inc(i, wg)
}
wg.Wait()
fmt.Println(counter)
func inc(i int, wg *sync.WaitGroup) {
defer wg.Done()
spin := 0
for {
old := counter
if atomic.CompareAndSwapInt32(&counter, old, old+1) {
break
} else {
spin++
if spin > 0 {
fmt.Println("i as : ", i, " , spin num : ", spin)
不對 counter 加鎖,在 inc 方法中,如果兩個 goroutine 在執行 old := counter 這一步時拿到的 counter 相等,那麼是否有可能這兩個 goroutine 在 compare 這一步結果同時為 true ?
如果不可能,那麼又是什麼原理呢?
比如一個簡單的 int 變數,在不對這個變數加鎖的情況下僅使用 CompareAndSwap 是如何實現原子操作的?
因為可能 2 個執行緒同時拿到了這個變數,那麼如果這時 2 個執行緒幾乎是同時 compare 的時候可能就是同時為 true。
那麼底層是否其實是存在類似鎖的實現呢?
舉個 Go 中協程的例子:
package main
import (
"fmt"
"sync"
"sync/atomic"
)
var counter int32 = 0
func main() {
n := 100
wg := new(sync.WaitGroup)
wg.Add(n)
for i:=0; i <n; i++ {
go inc(i, wg)
}
wg.Wait()
fmt.Println(counter)
}
func inc(i int, wg *sync.WaitGroup) {
defer wg.Done()
spin := 0
for {
old := counter
if atomic.CompareAndSwapInt32(&counter, old, old+1) {
break
} else {
spin++
}
}
if spin > 0 {
fmt.Println("i as : ", i, " , spin num : ", spin)
}
}
不對 counter 加鎖,在 inc 方法中,如果兩個 goroutine 在執行 old := counter 這一步時拿到的 counter 相等,那麼是否有可能這兩個 goroutine 在 compare 這一步結果同時為 true ?
如果不可能,那麼又是什麼原理呢?