20230402同步,互斥,PV操作

136 阅读4分钟

缘起

  • OS自考真题中10分大题会有这道,我目前做不出来,视频链接
  • 并发的一些代码题,我写不出来,现在看了一些API后,发现作者的思路,我没有读懂,根因应该是我不知道怎么去设计它,只有自己知道怎么做了,后面才是API的事
  • 看了b站的HIT的视频,2倍速听这块的时候就不大灵光,但日常面试又不会单独拿出来讲,都是生产者-消费者模型,读者-写者问题,而他们的基础是这个
  • 于是我又回头看下我那本薄的OS教材,以及B站上搜搜,形成了这个点

内容

前置概念

  • 临界区
    • 临界资源:系统中的资源一次只允许一个进程使用
    • 临界区:进程中访问临界资源的程序 lionel,我之前就没有真明白这个概念,只是觉得明白了,【就是一块代码段】
  • 信号量
    • HIT的b站视频里,提到了原来信号表示互斥关系时,表达不过来,就引入了信号量lionel,我理解就是bool类型表达不了,就要用int或结构体了
    • 信号量只能用于P和V操作
      • P是wait(),信号量小于0,进程状态置为等待状态【P是减,表示进程分配到一个资源了】
      • V是signal(),信号量小于等于0,释放等待队列中一个进程,将其置为就绪态 【V是加,表示进程释放了一个资源】

互斥(mutex)

  • 概念:
    • 互斥好理解,排它性使用,比如多进程竞争使用打印机,使用时就得锁一下,不让别人占用
  • PV操作
初始化信号量 S = 1;//这地方初化为1
进程A:
{
    P(S);
	临界区资源
	V(S);
}

进程B:
{
    P(S);
	临界区资源
	V(S)
}

//再有多个进程也没事

同步

  • 概念
    • 两个或多个进程共同完成一项工作,比如(生产打包)过程,A进程生产,B进程打包,只有等A生产出来了,B才能打包。
    • 人家描述是:让并发的进程,按我们想要的方式进行有序推进
  • PV操作
    • 简记就是前V后P,在后操作【打包】之前执行P(S),在前操作【生产】之后执行V(S)
初始化信号量S=0;//这地方初化为0
生产进程A:
{
    生产;
    V(S);
}

打包进程B:
{
    P(S);//在后操作之前执行P(S)
    打包;
}
  • 扩展一下
    • 3个进程怎么同步?

简单生产者-消费者问题

  • 模型
//缓冲区只能放1个,(空缓冲区数量empty信号量,初值为1)(满缓冲区数量full信号量,初值为0)
生产者P进程:
{
    while(true) {
        P(empty);
        生产;
        放入缓冲区;
        V(full);
    }
}

消费者Q进程:
{
    while(true) {
        P(full);
        取缓冲区; //前V后P
        V(empty);
        消费;
    }
}
void Producer() {
    while (true) {
        std::this_thread::sleep_for(std::chrono::milliseconds(5));// 休眠5毫秒

        std::unique_lock<std::mutex> lock(global_mutex);
        global_deque.push_front(1);
        std::cout << "生产者生产了数据" << std::endl;
        global_ConditionVar.notify_all();
    }
}

void Consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(global_mutex);

        // 当队列为空时返回false,则一直阻塞在这一行
        global_ConditionVar.wait(lock, [] {return !global_deque.empty(); });
        global_deque.pop_back();

        std::cout << "消费者消费了数据" << std::endl;
        global_ConditionVar.notify_all();
    }
}

小结

  • PV操作必须成对出现,互斥时,它们处于同一进程,同步时,它们不在同一进程中出现
  • 同步P操作与互斥P操作在一起时,同步P操作应出现在互斥P操作前
  • 互斥(S=1),同步(S=0)没太明白原因是啥,lionel

最后

进阶想懂一下

过程

  • 20230402先commit一版出来,后面再迭代,也是花了40min
  • 问题1:其实我没太想清楚,谁跟谁是同步或互斥关系,比如简单生产者-消费者问题里,到底只是同步关系,还是说又存在了互斥关系?书上也没说清楚
    • 解答:其实都是同步信号量,互斥的话要单独定义一个mutex,但至少书中的流程没提及