通过例子来学习 Go 和 Rust ---- RwLock 读写锁

Tericoder · · 1496 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

读写锁顾名思义就是只允许单进程同时写,在数据没有被写的情况下允许多进程同时读,的锁。

rust 里和 Mutex 类似,使用RAII(Resource Acquisition Is Initialization)来保证在值被Drop的时候自动解锁。而 go 里依然是需要手动解锁。

举个改写自Go标准库测试的栗子

import (
    . "sync"
    "sync/atomic"
)

const NumIterations = 1000
const NumReaders = 1000

func writer(rwm *RWMutex, activity *int32, cdone chan bool) {
    for i := 0; i < NumIterations; i++ {
        rwm.Lock()
        n := atomic.AddInt32(activity, 10000)
        if n != 10000 {
            panic(fmt.Sprintf("wlock(%d)\n", n))
        }
        atomic.AddInt32(activity, -10000)
        rwm.Unlock()
    }
    cdone <- true
}

func reader(rwm *RWMutex, activity *int32, cdone chan bool) {
    for i := 0; i < NumIterations; i++ {
        rwm.RLock()
        n := atomic.AddInt32(activity, 1)
        // 即使只获得了读锁,依旧可以修改数据
        // 只是禁止别的进程获取写锁
        if n < 1 || n > 10000 {
            panic(fmt.Sprintf("wlock(%d)\n", n))
        }
        atomic.AddInt32(activity, -1)
        rwm.RUnlock()
    }
    cdone <- true
}

func main() {
    var activity int32
    var rwm sync.RWMutex
    cdone := make(chan bool)
    go writer(&rwm, &activity, cdone)
    var i int
    for i = 0; i < NumReaders/2; i++ {
        go reader(&rwm, &activity, cdone)
    }
    go writer(&rwm, &activity, cdone)
    for ; i < NumReaders; i++ {
        go reader(&rwm, &activity, cdone)
    }
    for i := 0; i < 2+NumReaders; i++ {
        <-cdone
    }
}

把上面那个栗子改写成 Rust

use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, RwLock};
use std::thread;

const NumIterations: usize = 1000;
// 由于直接使用操作系统的 Thread,所以不能开太多
const NumReaders: usize = 500;

fn main() {
    let data = Arc::new(RwLock::new(0));
    let (tx, rx) = channel();
    {
        let (data, tx) = (data.clone(), tx.clone());
        thread::spawn(move || {
            writer(data, tx);
        });
    }
    for _ in 0..NumReaders/2 {
        let (data, tx) = (data.clone(), tx.clone());
        thread::spawn(move || {
            reader(data, tx);
        });
    }
    {
        let (data, tx) = (data.clone(), tx.clone());
        thread::spawn(move || {
            writer(data, tx);
        });
    }
    for _ in NumReaders/2..NumReaders {
        let (data, tx) = (data.clone(), tx.clone());
        thread::spawn(move || {
            reader(data, tx);
        });
    }
    for _ in 0..NumReaders {
        rx.recv();
    }
}

fn writer(data: Arc<RwLock<i32>>, tx: Sender<bool>) {
    for _ in 0..NumIterations {
        let mut w = data.write().unwrap();
        *w += 10000;
        assert!(*w == 10000);
        *w -= 10000;
    }
    tx.send(true);
}

fn reader(data: Arc<RwLock<i32>>, tx: Sender<bool>) {
    for _ in 0..NumIterations {
        // 只获得读锁是无法写数据的
        let r = data.read().unwrap();
        assert!(*r == 0);
    }
    tx.send(true);
}

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:Tericoder

查看原文:通过例子来学习 Go 和 Rust ---- RwLock 读写锁

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1496 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传