golang并发编程读写锁sync.RWMutex

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

内容简介:一、介绍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)


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

查看所有标签

猜你喜欢:

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

Responsive Web Design

Responsive Web Design

Ethan Marcotte / Happy Cog / 2011-6 / USD 18.00

From mobile browsers to netbooks and tablets, users are visiting your sites from an increasing array of devices and browsers. Are your designs ready? Learn how to think beyond the desktop and craft be......一起来看看 《Responsive Web Design》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具