zoukankan      html  css  js  c++  java
  • Golang的锁和线程安全的Map

    Golang的包sync实现了两种类型的锁: sync.Mutex 和 sync.RWMutex。通过阅读源代码我们可以知道sync.RWMutex是基于sync.Mutex实现的,其中的只读锁的实现使用类似引用计数的方式。

    对于任意 sync.Mutex 或 sync.RWMutex 变量l。 如果 n < m ,那么第n次 l.Unlock() 调用在第 m次 l.Lock()调用返回前发生。

    比如例子:

    package main

     

    import (

        "sync"

    )

     

    var l sync.Mutex

    var a string

     

    func f() {

        a = "hello, world"

        l.Unlock()

    }

     

    func main() {

        l.Lock()

        go f()

        l.Lock()

        print(a)

    }

    这个例子会输出 hello,world 的。

    因为,第一次 l.Unlock() 调用(在f函数中)在第二次 l.Lock() 调用(在main 函数中)返回之前发生,也就是在 print 函数调用之前发生。

    比如如果代码修改成下面方式,

    package main

     

    import (

        "sync"

    )

     

    var l sync.Mutex

    var a string

     

    func f() {

        a = "hello, world"

        print("21,")

        l.Unlock()

        print("22,")

    }

     

    func main() {

        l.Lock()

        print("1,")

        f()

        print("2,")

        l.Lock()

        print("3,")

        print(a)

    }

    执行结果是:1,21,22,2,3,hello, world

    如果代码改成下面方式

    package main

     

    import (

        "sync"

    )

     

    var l sync.Mutex

    var a string

     

    func f() {

        a = "hello, world"

        print("21,")

        l.Unlock()

        print("22,")

    }

     

    func main() {

        l.Lock()

        print("1,")

        go f()

        print("2,")

        l.Lock()

        print("3,")

        print(a)

    }

    执行结果是:1,2,21,22,3,hello, world

    下面代码来自:https://github.com/astaxie/beego/blob/master/safemap.go  用读写锁实现了 安全的map

    package beego

     

    import (

        "sync"

    )

     

    type BeeMap struct {

        lock *sync.RWMutex

        bm   map[interface{}]interface{}

    }

     

    func NewBeeMap() *BeeMap {

        return &BeeMap{

            lock: new(sync.RWMutex),

            bm:   make(map[interface{}]interface{}),

        }

    }

     

    //Get from maps return the k's value

    func (m *BeeMap) Get(k interface{}) interface{} {

        m.lock.RLock()

        defer m.lock.RUnlock()

        if val, ok := m.bm[k]; ok {

            return val

        }

        return nil

    }

     

    // Maps the given key and value. Returns false

    // if the key is already in the map and changes nothing.

    func (m *BeeMap) Set(k interface{}, v interface{}) bool {

        m.lock.Lock()

        defer m.lock.Unlock()

        if val, ok := m.bm[k]; !ok {

            m.bm[k] = v

        } else if val != v {

            m.bm[k] = v

        } else {

            returnfalse

        }

        return true

    }

     

    // Returns true if k is exist in the map.

    func (m *BeeMap) Check(k interface{}) bool {

        m.lock.RLock()

        defer m.lock.RUnlock()

        if _, ok := m.bm[k]; !ok {

            returnfalse

        }

        return true

    }

     

    func (m *BeeMap) Delete(k interface{}) {

        m.lock.Lock()

        defer m.lock.Unlock()

        delete(m.bm, k)

    }

    参考资料:

    go_mem   内存模型
    https://code.google.com/p/golang-china/wiki/go_mem
    http://hugozhu.myalert.info/2013/04/20/31-golang-memory-model.html

    Golang读写锁的实现源码
    http://golang.org/src/pkg/sync/rwmutex.go

    用读写锁实现的线程安全的Map
    https://github.com/astaxie/beego/blob/master/safemap.go

  • 相关阅读:
    项目报错二
    项目报错一
    OCP-1Z0-051-V9.02-21题
    Windows API——OpenClipboard——剪切板
    如果在CEdit中实现Ctrl+V、Ctrl+C、Ctrl+X的功能
    OCP-1Z0-051-V9.02-18题
    OCP-1Z0-051-V9.02-17题
    OCP-1Z0-051-V9.02-15题
    OCP-1Z0-051-V9.02-14题
    OCP-1Z0-051-V9.02-12题
  • 原文地址:https://www.cnblogs.com/ghj1976/p/3047528.html
Copyright © 2011-2022 走看看