美文网首页
CAS在go中的效率比较

CAS在go中的效率比较

作者: 听海吹牛逼的声音 | 来源:发表于2018-09-13 13:48 被阅读0次

    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中的效率比较

          本文链接:https://www.haomeiwen.com/subject/yiewgftx.html