PV 操作

news2024/9/23 7:28:51

PV 操作是一种实现进程 互斥同步 的有效方法。PV 操作与信号量的处理相关,P 表示 passeren 通过的意思,V 表示 vrijgeven 释放的意思. 包含在 1965 年, 由荷兰人 Dijkstra 提出的信号量机制; (同是 银行家算法 和 最短路径算法 的提出者)

术语:

  1. semaphore
  2. mutually-exclusive
  3. synchronization

介绍

  1. 信号量 S
  • S >= 0 表示某资源的的可用数;
  • S < 0 表示其绝对值表示阻塞队列中等待改资源的进程数;

P 操作表示 申请一个资源
V 操作表示 释放一个资源

  1. P 操作: S := S - 1
  • S >= 0, 则执行 P 操作的进程继续执行
  • S < 0, 则将执行该操作的进程置为阻塞状态, 并将其加入到 “阻塞队列”
  1. V 操作: S := S + 1
  • S > 0, V 操作继续
  • S <= 0, 则从阻塞队列唤醒一个进程, 并将其加入到 “就绪队列”

互斥与同步

  1. 互斥
    在这里插入图片描述
  2. 同步
  • 使用两个信号量来同步 (协作)
  1. buffer_empty: 空闲量

  2. buffer_full: 存放量
    在这里插入图片描述

  3. 同步与互斥的区别

同步是指两个进程协调来完成一件事情 (whole), 互斥则表示同一时刻只能有一个进程进入临界区 (fragment)

代码

  • ABA
class SemaphoreABA implements FooBar {

    private final int n;
    Semaphore foo = new Semaphore(6);
    Semaphore bar = new Semaphore(0);

    public SemaphoreABA(int n) {

        this.n = n;
    }

    public static void main(String[] args) {

        SemaphoreABA fooBar = new SemaphoreABA(10);
        new Thread(() -> {
            try {
                fooBar.foo(() -> System.out.print("Foo"));
            } catch (InterruptedException ignored) {
            }
        }).start();
        new Thread(() -> {
            try {
                fooBar.bar(() -> System.out.print("Bar"));
            } catch (InterruptedException ignored) {
            }
        }).start();
    }

    public void foo(Runnable printFoo) throws InterruptedException {

        for (int i = 0; i < n; i++) {
            foo.acquire();
            printFoo.run();
            bar.release();
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {

        for (int i = 0; i < n; i++) {
            bar.acquire();
            printBar.run();
            foo.release();
        }
    }

}
  • ABC
class SemaphoreThreadABC implements Foo {

    private final Semaphore s2;
    private final Semaphore s3;

    public SemaphoreThreadABC() {

        s2 = new Semaphore(0);
        s3 = new Semaphore(0);
    }

    public static void main(String[] args) {

        SemaphoreThreadABC foo = new SemaphoreThreadABC();
        new Thread(() -> {
            try {
                foo.second(() -> System.out.println("Two"));
            } catch (InterruptedException ignored) {
            }
        }).start();
        new Thread(() -> {
            try {
                foo.first(() -> System.out.println("One"));
            } catch (InterruptedException ignored) {
            }
        }).start();
        new Thread(() -> {
            try {
                foo.third(() -> System.out.println("Three"));
            } catch (InterruptedException ignored) {
            }
        }).start();
    }

    public void first(Runnable printFirst) throws InterruptedException {

        printFirst.run();
        s2.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {

        s2.acquire();
        printSecond.run();
        s3.release();
    }

    public void third(Runnable printThird) throws InterruptedException {

        s3.acquire();
        printThird.run();
    }

}

扩展

  1. 虚假唤醒 spurious wakeup (aka. 过早唤醒)

用 while 替换 if

if (state % 3 == 0) {
    // spurious wakeup
    System.out.print("A");
    state++;
    obj.await();
}
... // 虚假唤醒后, 继续往下走了

// 改正后
while (state % 3 == 0) {
    // spurious wakeup
    System.out.print("A");
    state++;
    obj.await();
}

在使用 notifyAll() 时, 所有线程全被唤醒, 但并不是所有线程都满足条件, 此时如果不用重新判断, 就会继续往下走

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1813740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytorch 实现简单的 线性回归 算法

Pytorch实现简单的线性回归算法 简单 tensor的运算 Pytorch涉及的基本数据类型是tensor&#xff08;张量&#xff09;和Autograd&#xff08;自动微分变量&#xff09; import torch x torch.rand(5, 3) #产生一个5*3的tensor&#xff0c;在 [0,1) 之间随机取值 y torch.o…

ATFX汇市:非农数据超预期靓丽,美指重新站上105关口

ATFX汇市&#xff1a;6月7日&#xff0c;美国劳工统计局公布5月份非农就业报告&#xff0c;其中提到&#xff1a;5月份增加了27.2万个岗位&#xff0c;大幅高于前值16.5万人&#xff0c;数据超预期靓丽&#xff1b;几个行业的就业人数继续呈上升趋势&#xff0c;其中医疗领域增…

操作系统 c语言模仿 磁盘文件操作

1&#xff0e;实验目的 深入了解磁盘文件系统的实现。 2&#xff0e;实验预备知识 文件的操作&#xff1b; 文件的逻辑结构和物理结构&#xff1b; 磁盘空间的管理&#xff1b; 磁盘目录结构。 3&#xff0e;实验内容 设计一个简单的文件系统&#xff0c;用文件模拟磁盘&…

springboot+vue前后端分离项目中使用jwt实现登录认证

文章目录 一、后端代码1.响应工具类2.jwt工具类3.登录用户实体类4.登录接口5.测试接口6.过滤器7.启动类 二、前端代码1.登录页index 页面 三、效果展示 一、后端代码 1.响应工具类 package com.etime.util;import com.etime.vo.ResponseModel; import com.fasterxml.jackson.…

RAG核心算法

一、分块与向量化 首先,我们的目标是创建一个向量索引,用以代表我们文档的内容,然后在运行时寻找所有这些向量与查询向量之间的最小余弦距离,以匹配最接近的语义含义。 1、分块 由于 Transformer 模型具有固定的输入序列长度,即便输入上下文窗口很大,一个句子或几个句…

【全网最有效,保姆级教程】KEPServerEX 6下载安装解决时长问题

1、下载KEPServer KEPServerEX 6下载链接(为了防止版本不兼容&#xff0c;一定要使用下面链接里面的版本&#xff01;)&#xff1a; https://pan.baidu.com/s/19pAXzhWa5nxduU3mi1V4Nw?pwd1234 提取码:1234 2、安装KEPServer 基本上都是默认下一步&#xff0c;选择中文&…

python中用列表实现栈

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 python中用列表实现栈 选择题 以下代码最后一次输出的结果是&#xff1f; stack [] stack.append(1) stack.append(2) stack.append(3) print(【显示】stack ,stack) print(【显示】stack.…

SpringCloud 前端-网关-微服务-微服务间实现信息共享传递

目录 1 网关获取用户校验信息并保存至请求头&#xff08;前端-网关&#xff09; 2 微服务获取网关中的用户校验信息&#xff08;网关-微服务&#xff09; 2.1 一般的做法是在公共的module中添加&#xff0c;此处示例为common 公共配置module中添加 2.2 定义拦截器 2.3 定义…

C++|哈希结构封装unordered_set和unordered_map

上一篇章&#xff0c;学习了unordered系列容器的使用&#xff0c;以及哈希结构&#xff0c;那么这一篇章将通过哈希结构来封装unordered系列容器&#xff0c;来进一步的学习他们的使用以及理解为何是如此使用。其实&#xff0c;哈希表的封装方式和红黑树的封装方式形式上是差不…

鸿蒙低代码开发的局限性

在版本是DevEco Studio 3.1.1 Release&#xff0c;SDK是3.1.0(API9) 的基础上。 1、低代码插件没有WebView组件。 2、低代码插件没有空白的自定义组件&#xff0c;当前提供的所谓自定义组件&#xff0c;只能用列表中提供的组件来拼接新的组件。 3、使用ets代码自定义的组件&…

JVM 常量池汇总

Tips JVM常量池分为静态常量池和运行时常量池&#xff0c;因为Jdk1.7后字符串常量池从运行时常量池存储位置剥离&#xff0c;故很多博客也是区分开来&#xff0c;存储位置和内容注意区别&#xff01; 字符串常量池底层是由C实现&#xff0c;是一个类似于HashTable的数据结构&am…

Spring 中使用MyBatis

一、Mybatis 的作用 1、MyBatis&#xff08;前身为iBatis&#xff09;是一个开源的Java持久层框架&#xff0c;它主要用于与数据库交互&#xff0c;帮助开发者更轻松地进行数据库操作。 持久层&#xff1a;指的是就是数据访问层(dao)&#xff0c;是用来操作数据库的。 2、MyB…

Filament 【表单操作】修改密码

场景描述&#xff1a; 新增管理员信息时需要填写密码&#xff0c;修改管理员信息时密码可以为空&#xff08;不修改密码&#xff09;&#xff0c;此时表单中密码输入有冲突&#xff0c;需要对表单中密码字段进项条件性的判断&#xff0c;使字段在 create 操作时为必需填写&…

深度学习-注意力机制和分数

深度学习-注意力机制 注意力机制定义与起源原理与特点分类应用领域实现方式优点注意力机制的变体总结注意力分数定义计算方式注意力分数的作用注意力分数的设计总结 注意力机制&#xff08;Attention Mechanism&#xff09;是一个源自对人类视觉研究的概念&#xff0c;现已广泛…

实测 WordPress 最佳优化方案:WP Super Cache+Memcached+CDN

说起 WordPress 优化加速来可以说是个经久不衰的话题了&#xff0c;包括明月自己都撰写发表了不少相关的文章。基本上到现在为止明月的 WordPress 优化方案已经固定成型了&#xff0c;那就是 WP Super CacheMemcachedCDN 的方案&#xff0c;因为这个方案可以做到免费、稳定、安…

如何用R语言ggplot2画高水平期刊散点图

文章目录 前言一、数据集二、ggplot2画图1、全部代码2、细节拆分1&#xff09;导包2&#xff09;创建图形对象3&#xff09;主题设置4&#xff09;轴设置5&#xff09;图例设置6&#xff09;散点颜色7&#xff09;保存图片 前言 一、数据集 数据下载链接见文章顶部 处理前的数据…

基于FreeRTOS+STM32CubeMX+LCD1602+MCP6S26(SPI接口)的6通道模拟可编程增益放大器Proteus仿真

一、简介: MCP6S26是模拟可 编程增益放大器(Programmable Gain Amplifiers, PGA)。它们可配置为输出 +1 V/V 到 +32 V/V 之间的增 益,输入复用器可通过 SPI 端口选择最多 6 个通道中的 一个。串行接口也可以将 PGA 置为关断模式,以降低 功耗。这些 PGA 针对高速度、低失调…

Python编程基础5

邮件编程 SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;简单邮件传输协议&#xff0c;使用TCP协议25端口&#xff0c;它是一组用于由源地址到目的地址传送邮件的规则&#xff0c;由它来控制信件的中转方式。python的smtplib提供了一种很方便的途径发送电子邮件。…

【python】tkinter GUI开发: Button和Entry的应用实战探索

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

MySQL----排序ORDER BY

在对数据进行处理的时候&#xff0c;我们通常需要对读取的数据进行排序。而 MySQL 的也提供了 ORDER BY 语句来满足我们的排序要求。 ORDER BY 可以按照一个或多个列的值进行升序&#xff08;ASC&#xff09;或降序&#xff08;DESC&#xff09;排序。 语法 SELECT column1…