rust学习(recursive mutex 实现)

问题:

编写如下代码的时候出现死锁:

pub fn test_double_lock() {
    let t = Arc::new(Mutex::new(1));

    let t1 = t.clone();
    let t2 = t.clone();

    let h = std::thread::spawn(move || {
        println!("hello trace1");
        let l1 = t1.lock().unwrap();
        println!("hello trace2");
        let l2 = t2.lock().unwrap();
        println!("hello trace3");
    });

    h.join().unwrap();
}

输出卡在了"hello trace2",这个原因主要是Rust的mutex是非recursive的 。所以同一个线程中如果出现2次获取锁,就会死锁掉。哈哈,网上查了一下,很多人都说recursive lock是垃圾代码,要修复。鉴于个人能力,很多这样的代码我都改不掉,所以我用Rust实现了一个recursive的锁。。。

主要数据结构

struct TarMutexRecord {
    m_count:u32, //1
    m_ownerid:Option<ThreadId> //2
}

pub struct TarMutex {
    m_record:Mutex<TarMutexRecord>, //3
    m_cond:Condvar //4
}

1.获取锁计数,如果计数到0的话,唤醒其他等待线程去拿锁

2.锁的owner,每次拿到锁以后记录拿锁线程,防止其他线程调用unlock释放

3.#1,#2的数据记录

4.如果锁的owner不是当前线程,则调用这个m_cond等待。当锁释放的时候,如果计数为0,唤醒m_cond等待的线程。

主要接口

pub fn lock(&self) {
        let tid = std::thread::current().id();
        loop {
            let mut lock = self.m_record.lock().unwrap();
            if lock.m_count == 0 {
                //no owner
                lock.m_count += 1; //1
                lock.m_ownerid = Some(tid); //2
                return;
            } else if let Some(ownerid) = lock.m_ownerid{
                if ownerid == tid {
                    lock.m_count += 1;//3
                    return;
                }
            }
            self.m_cond.wait(lock);//4
        }
    }

    pub fn unlock(&self) {
        let tid = std::thread::current().id();
        let mut lock = self.m_record.lock().unwrap();
        if let Some(ownerid) = lock.m_ownerid{
            if ownerid == tid {
                lock.m_count -= 1;//5
                if lock.m_count == 0 {
                    lock.m_ownerid = None;
                    self.m_cond.notify_all();//6
                }
            }
        }
    }

1.如果当前线程没有获取过锁,则只要计数+1

2.记录当前获取到锁线程id

3.如果当前线程已经获取过锁,则只要计数+1

4.如果当前有其他线程正在拿锁,则等待

5.锁释放时先计数-1

6.如果当前计数为0,表明锁都已经释放,直接唤醒所有等待锁的队列。

相关推荐

  1. rust学习(简单handler实现

    2024-04-10 14:32:01       20 阅读
  2. rust学习(recursive mutex 实现

    2024-04-10 14:32:01       15 阅读
  3. rust实现循环队列

    2024-04-10 14:32:01       19 阅读
  4. rust实现UDP服务器

    2024-04-10 14:32:01       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-10 14:32:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-10 14:32:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-10 14:32:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-10 14:32:01       18 阅读

热门阅读

  1. pytorch进阶

    2024-04-10 14:32:01       14 阅读
  2. leetcode2529--正整数和负整数的最大计数

    2024-04-10 14:32:01       13 阅读
  3. vs2019不能创建控制台程序

    2024-04-10 14:32:01       12 阅读
  4. LeetCode热题100

    2024-04-10 14:32:01       9 阅读
  5. 联邦学习中的差分隐私与同态加密

    2024-04-10 14:32:01       13 阅读
  6. 渗透工具及其知识库(个人笔记)

    2024-04-10 14:32:01       11 阅读
  7. 程序员如何搞副业?

    2024-04-10 14:32:01       12 阅读
  8. 关于可视化大屏适配

    2024-04-10 14:32:01       13 阅读
  9. LeetCode 518. 零钱兑换 II

    2024-04-10 14:32:01       13 阅读
  10. 代码学习记录39---动态规划

    2024-04-10 14:32:01       11 阅读
  11. 由于等待端口使用超时,无法启动内核

    2024-04-10 14:32:01       13 阅读
  12. 【C语言】关键字选择题

    2024-04-10 14:32:01       11 阅读