前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go 安全map 实现, 互斥锁和读写锁

go 安全map 实现, 互斥锁和读写锁

作者头像
solate
发布2019-07-22 16:51:44
4.5K0
发布2019-07-22 16:51:44
举报
文章被收录于专栏:solate 杂货铺solate 杂货铺

互斥锁

其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁.

代码语言:javascript
复制
package main

import (
	"fmt"
	"sync"
	"errors"
)

type MyMap struct {
	mp map[string]int
	mutex *sync.Mutex
}

func (this *MyMap) Get(key string) (int, error)  {
	this.mutex.Lock()
	i, ok := this.mp[key]
	this.mutex.Unlock()
	if !ok {
		return i, errors.New("不存在")
	}
	return i, nil
}

func (this *MyMap) Set(key string, v int)  {
	this.mutex.Lock()
	defer this.mutex.Unlock()
	this.mp[key] =  v
}

func (this *MyMap) Display()  {
	this.mutex.Lock()
	defer this.mutex.Unlock()
	for k,v := range this.mp  {
		fmt.Println(k, "=", v)
	}
}

func SetValue(m *MyMap) {
	var a rune
	a = 'a'
	for i:=0; i<10; i++  {
		m.Set(string(a+rune(i)),i)
	}
}


func main() {
	m := &MyMap{mp:make(map[string]int), mutex:new(sync.Mutex)}
	go SetValue(m) /*启动一个线程向 map 写入值*/
	go m.Display() /*启动一个线程读取 map 的值*/
	var str string /*这里主要是等待线程结束*/
	fmt.Scan(&str)
}

读写锁

读写锁即是针对于读写操作的互斥锁。它与普通的互斥锁最大的不同就是,它可以分别针对读操作和写操作进行锁定和解锁操作。读写锁遵循的访问控制规则与互斥锁有所不同。

在读写锁管辖的范围内,它允许任意个读操作的同时进行。但是,在同一时刻,它只允许有一个写操作在进行。并且,在某一个写操作被进行的过程中,读操作的进行也是不被允许的。

也就是说,读写锁控制下的多个写操作之间都是互斥的,并且写操作与读操作之间也都是互斥的。但是,多个读操作之间却不存在互斥关系。

代码语言:javascript
复制
package main

import (
	"fmt"
	"sync"
	"errors"
)

type MyMap struct {
	mp map[string]int
	mutex *sync.RWMutex
}

func (this *MyMap) Get(key string) (int, error)  {
	this.mutex.RLock()
	i, ok := this.mp[key]
	this.mutex.RUnlock()
	if !ok {
		return i, errors.New("不存在")
	}
	return i, nil
}

func (this *MyMap) Set(key string, v int)  {
	this.mutex.RLock()
	defer this.mutex.RUnlock()
	this.mp[key] =  v
}

func (this *MyMap) Display()  {
	this.mutex.RLock()
	defer this.mutex.RUnlock()
	for k,v := range this.mp  {
		fmt.Println(k, "=", v)
	}
}

func SetValue(m *MyMap) {
	var a rune
	a = 'a'
	for i:=0; i<10; i++  {
		m.Set(string(a+rune(i)),i)
	}
}


func main() {
	m := &MyMap{mp:make(map[string]int), mutex:new(sync.RWMutex)}
	go SetValue(m) /*启动一个线程向 map 写入值*/
	go m.Display() /*启动一个线程读取 map 的值*/
	var str string /*这里主要是等待线程结束*/
	fmt.Scan(&str)
}
读写锁小例子
代码语言:javascript
复制
package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var lock sync.RWMutex
	go read(&lock)
	go read(&lock)
	go write(&lock)
	time.Sleep(25000000)
	fmt.Println("end")
}

func read(lock *sync.RWMutex) {
	lock.RLock()
	fmt.Println("reading")
	time.Sleep(5000)
	fmt.Println("read end")
	lock.RUnlock()
}

func write(lock *sync.RWMutex) {
	time.Sleep(1000)//保证先让读拿到锁, 如果没有就会随机,不过应该先过read一般会先read.
	lock.Lock()
	fmt.Println("writing")
	time.Sleep(5000)
	fmt.Println("write end")
	lock.Unlock()
}


//结果
reading
reading
read end
read end
writing
write end
end

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 互斥锁
  • 读写锁
    • 读写锁小例子
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档