CAS在go中的效率比较

CAS(compare and swap)https://en.wikipedia.org/wiki/Compare-and-swap
Go中的sync/atomic基于CAS做到lock free。想了解下效率怎么样,写了个简单例子。
在race condition特别严重的时候,也就是两个goroutine一直在抢着修改同一个对象的时候,CAS的表现和加锁mutex的效率差不多,时高时低。 但是在没有race condition的时候,CAS的表现比mutex耗时要第一个数量级,原因也很明显,CAS在compare失败的时候回重试,所以在race严重的时候retry多,耗时偶尔炒锅mutex。但是在race没有或者小的时候,效率就体现出来了,因为没有retry,儿mutex还是需要加锁和解锁。耗时仅仅是无锁时间的两倍时间。
总结起来,多数情况下能用CAS做到lock free是比较好的,因为没有那么大量的race condition.

result:

No lock:  -109178
29.617844ms
Mutex lock with condition race:  0
344.894102ms
Atomic CAS with condition race:  0
355.517159ms
Mutex lock without condition race:  10000000
179.974834ms
Atomic CAS without condition race:  10000000
54.245469ms
package main

import (
    "fmt"
    "sync"
    "time"
    "sync/atomic"
)
var wg sync.WaitGroup
var lock sync.Mutex
var times = 10000000
func add(x *int) {
    for i := 0; i < times; i++ {
        *x++
    }
    wg.Done()
}

func sub(x *int) {
    for i := 0; i < times; i++ {
        *x--
    }
    wg.Done()
}

func addMutex(x *int) {
    for i := 0; i < times; i++ {
        lock.Lock()
        *x++
        lock.Unlock()
    }
    wg.Done()
}

func subMutex(x *int) {
    for i := 0; i < times; i++ {
        lock.Lock()
        *x--
        lock.Unlock()
    }
    wg.Done()
}

func addAtomic(x *int32) {
    for i := 0; i < times; i++ {
        atomic.AddInt32(x, 1)
    }
    wg.Done()
}

func subAtomic(x *int32) {
    for i := 0; i < times; i++ {
        atomic.AddInt32(x, -1)
    }
    wg.Done()
}

func main() {
    x := 0
    start := time.Now()
    wg.Add(2)
    go add(&x)
    go sub(&x)
    wg.Wait()
    fmt.Println("No lock: ", x)
    elasped := time.Since(start)
    fmt.Println(elasped)

    start = time.Now()
    wg.Add(2)
    x = 0
    go addMutex(&x)
    go subMutex(&x)
    wg.Wait()
    fmt.Println("Mutex lock with condition race: ", x)
    elasped = time.Since(start)
    fmt.Println(elasped)

    start = time.Now()
    wg.Add(2)
    var y int32 = 0
    go addAtomic(&y)
    go subAtomic(&y)
    wg.Wait()
    fmt.Println("Atomic CAS with condition race: ", y)
    elasped = time.Since(start)
    fmt.Println(elasped)

    start = time.Now()
    wg.Add(1)
    x = 0
    go addMutex(&x)
    wg.Wait()
    fmt.Println("Mutex lock without condition race: ", x)
    elasped = time.Since(start)
    fmt.Println(elasped)

    start = time.Now()
    wg.Add(1)
    y = 0
    go addAtomic(&y)
    wg.Wait()
    fmt.Println("Atomic CAS without condition race: ", y)
    elasped = time.Since(start)
    fmt.Println(elasped)
}

你可能感兴趣的:(CAS在go中的效率比较)