go language coroutine security map

Preface:

In the go language map is very important data structure. Map is a disordered collection of key-value pairs. Map the most important point is to quickly retrieve data by key, key index similar to, point to the value of the data. The question is, so cozy data structure, it is not a coroutine safe! When multiple coroutine on a map to read and write at the same time, will throw a fatal error. Summarize what you want to do coroutine security map a total of the following three methods.

 

1.map + Lock

This is the most common type of operation, when you want to map to the operation of the lock, the other coroutine to wait. The following sample code is:

package util

import "sync"

type SafeMap struct {
    Data map[string]interface{}
    Lock sync.RWMutex
}

func (this *SafeMap) Get(k string) interface{} {
    this.Lock.RLock()
    defer this.Lock.RUnlock()
    if v, exit := this.Data[k]; exit {
        return v
    }
    return nil
}

func (this *SafeMap) Set(k string, v interface{}) {
    this.Lock.Lock()
    defer this.Lock.Unlock()
    if this.Data == nil {
        this.Data = make(map[string]interface{})
    }
    this.Data[k] = v
}

  

 

2. sync.map

This is the most recent version go to the new security map == coroutine may be necessary official also feel quite right. The following code to write about the main use. I have not introduced specific principles. Here we must note sync.map not require initialization

Test sync.Map var 

// element disposed 
FUNC SET (K, V interface {}) { 
    test.Store (K, V) 
} 

// get element 
FUNC GET (interface {K})} {{interface 
    TEM, Exit: = test.Load (K) 
    IF Exit { 
        return TEM 
    } 
    return nil 
} 

// pass a function, internal sync.map iterates, run the function 
FUNC ranggfunc (funcs FUNC (Key, interface {value}) BOOL) { 
    Test. the Range (funcs) 
} 

// remove elements 
FUNC del (Key interface {}) { 
    test.Delete (Key) 
}

 

 

3. Single coroutine operation map, communication with channle

The idea of ​​a little show, that has a map by the co-operation process, other coroutine by channle tell how this co-operation should drive. In fact, this way is not very good performance, but also because channle bottom lock, and map data stored is to calculate the hash, and before multiple coroutines count their own hash, has now become a coroutine calculated. But this idea still can, so you can not just operate on the map. socket communication, ah, ah call the globally unique object, you can use this idea. Below we look at the code I realized:

package main

import (
    "fmt"
    //"time"
)

var (
    ADD  interface{} = 1
    DEL  interface{} = 2
    GET  interface{} = 3
)


type safeMap struct {
    Msq     chan *[3] interface{}       //['type','id','value',channle]
    data    map[interface{}]interface{}
    chanl   chan interface{}
}

func NewSafeMap() *safeMap {
    tem := &safeMap{}
    tem.init()
    return tem
}

func (this *safeMap) init() {
    this.Msq   = make(chan *[3]interface{},10)
    this.data  = make(map[interface{}]interface{})
    this.chanl = make(chan interface{},0)
    go this.run()
}

func (this *safeMap) run() {
    for {
        select {
        case msg := <- this.Msq :
            switch msg[0] {
            case ADD :
                this.dataAdd(msg[1],msg[2])
            case DEL :
                this.dataDel(msg[1])
            case GET :
                this.dataGet(msg[1])
            }
        }
    }
}

func (this *safeMap) msqChan (typ,id,val interface{}) *[3]interface{}{
    return &[...]interface{}{typ,id,val}
}

//保存 或者更新元素
func (this *safeMap) dataAdd (id , value interface{}) {
    this.data[id] = value
}

//删除元素
func (this *safeMap) dataDel (id interface{}) {
    delete(this.data,id)
}

//获得元素
func (this *safeMap) dataGet (id interface{}) {
    if val ,exit := this.data[id] ;exit {
        this.chanl <- val
        return
    }
    this.chanl <- nil
}

//----------------------------------------------------对外接口--------------------------------
func (this *safeMap) Add (id ,value interface{}) {
    this.Msq <- this.msqChan(ADD,id,value)
}

func (this *safeMap) Del (id interface{}) {
    this.Msq <- this.msqChan(DEL,id ,nil)
}

func (this *safeMap) Get (id interface{}) interface{} {
    this.Msq <- this.msqChan(GET,id,nil)
    res := <- this.chanl
    return res
}

//获得 长度
func (this *safeMap) GetLength() uint32{
    return uint32(len(this.data))
}


func main() {
    sa := NewSafeMap()

//  sa.Add(1,1)
    sa.Add(2,3)
    fmt.Println(2,sa.Get(2))
    sa.Del(2)
    fmt.Println(2,sa.Get(2))
}

  

 

Guess you like

Origin www.cnblogs.com/wsw-seu/p/11665855.html