当前位置: 首页 > article >正文

<mutex>注释 12:重新思考与猜测、补充锁的睡眠与唤醒机制,结合 linux0.11 操作系统代码的辅助(下)

(60)继续分析,为什么 timed_mutex 可以拥有准时的等待时间

在这里插入图片描述

++逐步测试

在这里插入图片描述

++ 以及:

在这里插入图片描述

++以及:

在这里插入图片描述

++ 以及:

在这里插入图片描述

++ 上面的例子里之所以这么编写。无论 timed_mutex 里的定时等待函数,还是 条件变量 condition_variable 里的限时 wait_xx (…) 函数。最终都是调用上面的函数完成定时等待。所以手工为其凑齐了参数。直接调用了这个函数

在这里插入图片描述

(61) 列出简化版的 mutex 与 condition_variable 的源代码

在这里插入图片描述

++ 以及:

在这里插入图片描述

++ 根据上面的大量的测试,结合 linux 0.11 上的进程睡眠与唤醒的规律,推测一下上图中这些不同底层函数的功能。锁 mutex 的 加锁解锁,应该属于 不可中断睡眠状态,task_uninterruptable 。这类睡眠由 mutex . unlock () 来唤醒等待锁的线程。 条件变量是为了线程同步,避免线程的无意义的无序竞争锁,比如同一文件的读写线程之间的竞争,此情形就可以由 条件变量来规范线程的睡眠与唤醒。 调用了 condition_variable . wait ()的线程也会进入睡眠状态,但不是在锁上睡眠,而是在条件变量上睡眠,只可以由对应的 condition_variable . notify ()等函数来唤醒线程,然后这些被唤醒的线程再去竞争锁。所以在条件变量上睡眠的线程也属于在不可中断睡眠状态 task_uninterruptable 。因为 锁有 80 字节的内存,条件变量有 72 字节的内存,所以锁与条件变量都可以记录其上的睡眠线程的 id 的,或者是 线程控制块的地址 TCB ,以便于将来唤醒这些线程。 条件变量上的定时睡眠,应该属于 可中断睡眠状态 task_interruptable , 因为该线程要响应定时信号 SIGALRM ,以便在定时到时由操作系统唤醒,改为可运行状态 task_running 。但定时睡眠后,(包括 条件变量上的无限睡眠状态 condition_variable . wait ()),从条件变量上醒来后的线程,都要去竞争锁 mutex ,得不到锁的线程,还会再次进入睡眠状态,改为在 锁 mutex 上睡眠。下一次就不是条件变量来唤醒了,而是由 锁 mutex . unlock() 来唤醒。而且也对应了另一句话,在条件变量上睡眠的线程在调用 wait()前必须先持有锁。由 条件变量释放锁后把线程放在条件变量上睡眠,条件变量上的睡眠线程,醒来后的第一件事就是参与锁的竞争。条件变量上的限时睡眠,也可以被提前唤醒,但若断言条件不满足,还会继续睡眠,直到把指定的时间用完。

(62)至此,基本理清了定时锁 timed_mutex 为什么具有精确的醒来功能了,不会超时睡眠。因为 timed_mutex 中的 锁
timed_mutex . _My_mutex 是一直闲置的,不经常被加锁,所以定时睡眠的线程醒来后一定可以拿到这个锁。但 timed_mutex . _My_locked 这个整型数据的是否为 0 的语义,才表示临界资源是否空闲。锁 timed_mutex . _My_mutex 是为了在写 timed_mutex . _My_locked 时保护一下这个整形数据,然后就释放锁了。有点类似于双重锁定的功能与感觉。

类似的结构体设计,还有线程间共享数据,共享函数返回值的结构 _Associated_state《T》

在这里插入图片描述

++ 继续:

在这里插入图片描述

++ 也给出上面图的代码版本:

template <class _Ty>
struct _State_manager // class future : public _State_manager<_Ty>
{
    _Associated_state<_Ty>* _Assoc_state; 
    bool _Get_only_once; 
// 当 本模板 作为 future        的父类时,_Get_only_once 为 true ;
// 当 本模板 作为 shared_future 的父类时,_Get_only_once 为 false
    void wait()  {   _Assoc_state->_Wait();   }

    template <class _Rep, class _Per> // wait for duration
    future_status 
    wait_for(const chrono::duration<_Rep, _Per>& _Rel_time)
    {   return _Assoc_state->_Wait_for(_Rel_time);    }

    template <class _Clock, class _Dur> // wait until time point
    future_status 
    wait_until(const chrono::time_point<_Clock, _Dur>& _Abs_time) 
    {   return _Assoc_state->_Wait_until(_Abs_time);  }
};

template <class _Ty>
class _Associated_state  //用于管理关联同步状态的类
{
    virtual void _Wait() {  
        unique_lock<mutex> _Lock(_Mtx);   
        _Maybe_run_deferred_function(_Lock);

        while (!_Ready)     _Cond.wait(_Lock); 
    }

    template <class _Rep, class _Per>   // wait for duration
    future_status _Wait_for( chrono::duration<_Rep, _Per>& _Rel_time)  {
        unique_lock<mutex> _Lock(_Mtx);
        if (_Has_deferred_function())    return future_status::deferred;

        if (_Cond.wait_for(_Lock, _Rel_time, _Test_ready(this)))     
            return future_status::ready;

        return future_status::timeout;
    }

    template <class _Clock, class _Dur>  // wait until time point
    future_status _Wait_until( chrono::time_point<_Clock, _Dur>& _Abs_time) {
        unique_lock<mutex> _Lock(_Mtx);
        if (_Has_deferred_function())       return future_status::deferred;

        if (_Cond.wait_until(_Lock, _Abs_time, _Test_ready(this)))    
            return future_status::ready;

        return future_status::timeout;
    }
};

(63)

谢谢


http://www.kler.cn/a/444401.html

相关文章:

  • PostgreSQL技术内幕21:SysLogger日志收集器的工作原理
  • QT c++ 测控系统 一套报警规则(上)
  • ArcGIS计算土地转移矩阵
  • 基于springboot的在线政务服务系统的设计与实现-仅供学习
  • C语言中信号量:<semaphore.h>头文件
  • Ubuntu系统安装MySQL
  • LabVIEW在电液比例控制与伺服控制中的应用
  • 基于Spring Boot的校园商城系统
  • es 3期 第16节-运用启发式特性引导用户查询
  • 个人秋招总结
  • 探索 CI/CD 工具的力量
  • 机械鹦鹉与真正的智能:大语言模型推理能力的迷思
  • 3、交换机IP路由功能
  • git企业开发的相关理论(二)
  • 使用xjar 对Spring-Boot JAR 包加密运行
  • GO OSS 前端直传 Presign
  • 快速解决oracle 11g中exp无法导出空表的问题
  • InnoDB 查询成本
  • 【Leetcode Top 100】105. 从前序与中序遍历序列构造二叉树
  • Python:动态粒子爱心
  • Spring IOC 和 AOP的学习笔记
  • Spring篇--xml方式整合第三方框架
  • linux CentOS系统上卸载docker
  • Android Binder 进程间通信
  • 肝了半年,我整理出了这篇云计算学习路线(新手必备,从入门到精通)
  • Diffusino Policy学习note