golang并发编程读写锁sync.RWMutex

栏目: Go · 发布时间: 6年前

内容简介:一、介绍sync.RWMutex 为读写锁,lock为写锁定 ,Unlock 为写解锁,RLock为读锁,RUnlock为读解锁。二、场景

一、介绍

sync.RWMutex 为读写锁,lock为写锁定 ,Unlock 为写解锁,RLock为读锁,RUnlock为读解锁。

二、场景

适用于场景:多读一写,读可以同时进行,但是写只能一个写,读写是互斥的要么只能读或者只能写

三、代码测试

功能性测试

第一种场景 测试内容 : 读锁存在的情况下,同时出现读和写的操作,此时优先获取写锁

package main

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

var rwlock = &sync.RWMutex{}
var wg = &sync.WaitGroup{}

func TestRWMutex(t *testing.T) {
    //读
    wg.Add(1)
    go rlockwork()

    time.Sleep(2 * time.Second)
    //读
    wg.Add(1)
    go rlock()
    //写
    wg.Add(1)
    go wlock()

    wg.Wait()
}
func wlock() {

    rwlock.Lock()
    fmt.Println("加写锁")
    fmt.Println("写任务执行")
    defer func() {
        rwlock.Unlock()
        fmt.Println("最后写解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开写锁")
}
func rlock() {
    rwlock.RLock()
    fmt.Println("加读锁")
    fmt.Println("读任务执行")
    defer func() {
        rwlock.RUnlock()
        fmt.Println("最后读解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开读锁")
}
func rlockwork() {
    rwlock.RLock()
    fmt.Println("加读锁====首先获取读锁")
    fmt.Println("读任务执行")
    time.Sleep(4 * time.Second)
    defer func() {
        rwlock.RUnlock()
        fmt.Println("最后读解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开读锁")
}

输出结果:

=== RUN   TestRWMutex
加读锁====首先获取读锁
读任务执行
准备解开读锁
最后读解锁完毕
加写锁
写任务执行
准备解开写锁
最后写解锁完毕
加读锁
读任务执行
准备解开读锁
最后读解锁完毕
--- PASS: TestRWMutex (4.00s)
PASS
Process finished with exit code 0

第二种场景 功能性测试

测试内容: 同时开启2个线程去争夺读锁和写锁,此时都有机会被获取

package main

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

var rwlock = &sync.RWMutex{}
var wg = &sync.WaitGroup{}

func TestRWMutex(t *testing.T) {
    //读
    //wg.Add(1)
    //go rlockwork()

    time.Sleep(2 * time.Second)
    //读
    wg.Add(1)
    go rlock()
    //写
    wg.Add(1)
    go wlock()

    wg.Wait()
}
func wlock() {

    rwlock.Lock()
    fmt.Println("加写锁")
    fmt.Println("写任务执行")
    defer func() {
        rwlock.Unlock()
        fmt.Println("最后写解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开写锁")
}
func rlock() {
    rwlock.RLock()
    fmt.Println("加读锁")
    fmt.Println("读任务执行")
    defer func() {
        rwlock.RUnlock()
        fmt.Println("最后读解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开读锁")
}
func rlockwork() {
    rwlock.RLock()
    fmt.Println("加读锁====首先获取读锁")
    fmt.Println("读任务执行")
    time.Sleep(4 * time.Second)
    defer func() {
        rwlock.RUnlock()
        fmt.Println("最后读解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开读锁")
}

输出结果:

=== RUN   TestRWMutex
加写锁
写任务执行
准备解开写锁
最后写解锁完毕
加读锁
读任务执行
准备解开读锁
最后读解锁完毕
--- PASS: TestRWMutex (2.00s)
PASS

Process finished with exit code 0

分割线======================================分割线

=== RUN   TestRWMutex
加读锁
读任务执行
准备解开读锁
最后读解锁完毕
加写锁
写任务执行
准备解开写锁
最后写解锁完毕
--- PASS: TestRWMutex (2.00s)
PASS

Process finished with exit code 0

第三种场景 功能性测试

测试内容:写锁存在的情况,同时开启2个线程去争夺读锁和写锁,优先获取读锁

package main

import (
    "testing"
    "fmt"
    "sync"
    "time"
    "runtime"
)

var rwlock = &sync.RWMutex{}
var wg = &sync.WaitGroup{}

func TestRWMutex(t *testing.T) {
    //写
    runtime.GOMAXPROCS(runtime.NumCPU())
    wg.Add(1)
    go wlock()

    time.Sleep(2 * time.Second)
    //读
    wg.Add(1)
    go rlock()
    //写
    wg.Add(1)
    go wlock()

    wg.Wait()
}
func wlock() {
    rwlock.Lock()
    fmt.Println("加写锁")
    fmt.Println("写任务执行")
    time.Sleep(4 * time.Second)
    defer func() {
        rwlock.Unlock()
        fmt.Println("最后写解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开写锁")
}
func rlock() {
    rwlock.RLock()
    fmt.Println("加读锁")
    fmt.Println("读任务执行")
    defer func() {
        rwlock.RUnlock()
        fmt.Println("最后读解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开读锁")
}
func rlockwork() {
    rwlock.RLock()
    fmt.Println("加读锁====首先获取读锁")
    fmt.Println("读任务执行")
    //time.Sleep(4 * time.Second)
    defer func() {
        rwlock.RUnlock()
        fmt.Println("最后读解锁完毕")
        wg.Done()
    }()
    fmt.Println("准备解开读锁")
}

输出结果:

=== RUN   TestRWMutex
加写锁
写任务执行
准备解开写锁
最后写解锁完毕
加读锁
读任务执行
准备解开读锁
最后读解锁完毕
加写锁
写任务执行
准备解开写锁
最后写解锁完毕
--- PASS: TestRWMutex (8.01s)
PASS

Process finished with exit code 0

总结:

1.读锁存在的情况下,同时出现读和写的操作,此时优先获取写锁

2.同时开启2个线程去争夺读锁和写锁,此时都有机会被获取

3.写锁存在的情况,同时开启2个线程去争夺读锁和写锁,优先获取读锁

注:(golang版本go version go1.11.4 darwin/amd64)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

长尾理论

长尾理论

[美]克里斯·安德森 / 中信出版集团股份有限公司 / 2015-8-1 / 59.00元

互联网时代,大众市场不再一统天下,小众市场也可以呼风唤雨。 在《长尾理论》一书中,克里斯·安德森详细阐释了长尾的精华所在,指出商业和文化的未来不在于传统需求曲线上那个代表“畅销商品”的头部,而是那条代表“冷门商品”的经常被人遗忘的长尾。尽管我们仍然对热门商品着迷,但它们对消费者的吸引力已经大不如从前,因为市场已经大大分化。黄金电视节目的收视率几十年来一直在萎缩,若是在七八十年代,现在的一档最......一起来看看 《长尾理论》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具