Linux操作系统-信号量

2023-05-16

信号量也属于一种进程间通信的机制,与其他的进程间通信不同,信号量不是用来传输数据的,而是用来进程间同步与互斥。除此之外,信号量还可以实现线程间的互斥

信号量是什么?

信号量的本质是一个计数器。

一个信号量是由一个内核维护的整数,它的值被限制在大于等于0。对信号量可以进行以下操作:

1、将信号量设置一个值。

2、在信号量当前值的基础上加上一个数量(V操作)。

3、在信号量当前值的基础上减去一个数量(P操作)。

4、当信号量的值为0时,会被阻塞。

既然是计数器,那么其中的count也是临界资源,所以PV操作必须得是原子的。

Linux下信号量的P.V操作如何保证其原子性_weixin_34402090的博客-CSDN博客

P操作

相当于count--;

P(){
        lock();
        if(count)
            count--;
        else
            wait(); // 阻塞
        unlock();
}

V操作

相当于count++

V(){
        lock();
        count++;
        if(count<=0)
            wakeup();//唤醒
        unlock();
}

注意:V操作的唤醒进程或者线程是不确定的,即具体是哪个进程或者线程被唤醒并允许递减这个信号量是不确定的,仅仅是一个同步机制,而不是一个排队机制。


POSIX信号量

头文件 semaphore.h

1、初始化一个信号量

sem_init函数

sem_t 声明一个信号量;

sem_init函数使用value中指定的值对sem指向的信号量进行初始化。通俗一点就是给信号量中的count值赋一个初值。

第二个参数要注意

pshared表明这个信号量是在线程间共享还是在进程间共享。

如果pshared=0,这个信号量会在调用进程中的线程间进行共享。此时这个信号量应该为临界资源,让线程都可以看到。

如果pshared=1,这个信号量在进程间共享。此时需要放在内存共享区,即共享内存或者mmap映射区域。

2、P操作

sem_wait()函数

sem_wait函数就是让sem指向的信号量的值减1.

如果信号量的当前值大于0,则sem_wait立即返回。如果信号量的当前值小于0,那么sem_wait会阻塞到信号量的值大于0为止。

 

3、V操作

sem_post函数

sem_post函数就是将sem指向的信号量的值+1。

如果在sem_post调用之前信号量的值为0,并且其他某个进程(线程)正在因为等待递减这个信号量而阻塞,那么该进程(线程)会被唤醒。

4、销毁一个信号量

sem_destroy函数

 

sem必须被sem_init初始化才能被销毁

只有在不存在进程或线程在等待一个信号量时才能够安全销毁这个信号量。


用信号量实现线程互斥

用信号量来代替互斥锁mutex。

思想:将信号量设置为0,1两个状态,这样就可以达到互斥锁的效果。

//一个简单的抢票程序
#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>                                                 
using namespace std;
class myclass
{
private:
    sem_t mtx;
    int ticket = 5000;
public:
    myclass()
    {
        sem_init(&mtx, 0, 1);//设置大小为1即和锁一样的特点
    }
    ~myclass()
    {
        sem_destroy(&mtx);
    }
    void P()//封装一下PV操作的函数
    {
        sem_wait(&mtx);
    }
    void V()
    {
        sem_post(&mtx);
    }
    void Run()
    {
        pthread_t tid[4];
        for (int i = 0; i < 4; i++)//创建四个线程
            pthread_create(tid + i, nullptr, Routine, this);
        for (int i = 0; i < 4; i++)
            pthread_join(tid[i], nullptr);
    }
    static void* Routine(void* arg)
    {
        myclass* ptr = (myclass*)arg;
        while (1)
        {
            ptr->P();
            if (ptr->ticket > 0)
            {
                usleep(1000);
                cout << "i am thread " << pthread_self() << ", i get tikcet num is " << ptr->ticket << endl;
                (ptr->ticket)--;
                ptr->V();
            }
            else
            {
                ptr->V();
                break;
            }
        }
        return nullptr;
    }
};
int main()
{
    myclass mc;
    mc.Run();
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux操作系统-信号量 的相关文章

  • pprof 和 ps 之间的内存使用差异

    我一直在尝试分析用 cobra 构建的 cli 工具的堆使用情况 这pprof工具显示如下 Flat Flat Sum Cum Cum Name Inlined 1 58GB 49 98 49 98 1 58GB 49 98 os Read
  • dlopen 或 dlclose 未调用信号处理程序

    我在随机时间内收到分段错误 我注册了信号 但发生分段错误时未调用信号处理程序 include
  • 从 Python 访问 802.11 无线管理帧

    我想从 Linux 上的 Python 嗅探 802 11 管理 探测请求 帧 这可以从 Scapy 中实现 如下所示 coding utf 8 from scapy all import def proc p if p haslayer
  • 错误:命令“c++”失败,退出状态为 1

    所以我尝试按照以下说明安装 Pyv8https andrewwilkinson wordpress com 2012 01 23 integrating python and javascript with pyv8 https andre
  • 查看 Linux 上的多核或多 CPU 利用率

    我有一个在 Linux 上运行的程序 我需要确定它如何利用所有 CPU 内核 有没有什么程序可以查看这些信息 跑过 top 命令并按下 1 查看各个核心
  • 如何设置Java线程的CPU核心亲和力?

    我搜索了以前关于类似主题的帖子 但找不到合适的答案 因此提出这个问题 非常感谢您帮助回答 我知道在 Linux 中通过任务集命令设置进程与特定 CPU 核心的关联性 但我想设置 Java 线程与特定 cpu 核心的亲和力 以便属于同一进程的
  • 在 Docker 容器中以主机用户身份运行

    在我的团队中 我们在进行开发时使用 Docker 容器在本地运行我们的网站应用程序 假设我正在开发 Flask 应用程序app py具有依赖关系requirements txt 工作流程大致如下 I am robin and I am in
  • Python将文件从Linux复制到WIndows

    我正在构建一个网站 该网站有一个表单 可以捕获用户数据并在用户数据上运行一些cgi cgi 的第一步是需要将文件从 Linux Web 服务器复制到 Windows 计算机 服务器将使用 Active Directory 角色帐户作为复制凭
  • SMP 上如何处理中断?

    SMP 对称多处理器 多核 机器上如何处理中断 内存管理单元是只有一个还是多个 假设两个线程 A 和 B 运行在不同的内核上 同时 访问页表中不存在的内存页面 在这种情况下 将会出现页面错误 并从内存中引入新页面 将会发生的事件的顺序是什么
  • 如何列出 nginx 中的所有虚拟主机

    有没有一个命令可以列出 CentOS 上 nginx 下运行的所有虚拟主机或服务器 我想将结果通过管道传输到文本文件以用于报告目的 我正在寻找与我用于 Apache 的命令类似的命令 apachectl S 2 gt 1 grep 端口 8
  • 如何在perl中使用O_ASYNC和fcntl?

    我想使用 O ASYNC 选项 当管道可以读取时 SIGIO 的处理程序将运行 但以下代码不起作用 任何人都可以帮助我吗 bin env perl use Fcntl SIG IO sub print catch SIGIO n my fl
  • 完整的 C++ i18n gettext()“hello world”示例

    我正在寻找完整的 i18ngettext 你好世界的例子 我已经开始了一个基于的脚本使用 GNU gettext 的本机语言支持教程 https web archive org web 20130330233819 http oriya s
  • 在非实时操作系统/内核上执行接近实时任务的最佳方法是什么?

    在一台 GNU Linux 机器上 如果想要执行 实时 亚毫秒级时间关键 任务 您几乎总是必须经历漫长 复杂且容易出现问题的内核补丁过程 以提供足够的支持 1 http en wikipedia org wiki RTLinux Backg
  • 提高mysql导入速度[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我有一个很大的数据库22GB 我曾经用过进行备份mysqldumpgzip 格式的命令 当我提取 gz 文件时 它会生成 sql文件的
  • pthread_self() 返回的线程 ID 与调用 gettid(2) 返回的内核线程 ID 不同

    这句话来自于pthread self 的手册页 http linux die net man 3 pthread self 那么 我应该根据什么来决定是否应该使用pthread self or gettid确定哪个线程正在运行该函数 两者都
  • 套接字发送调用被阻塞很长时间

    我每 10 秒在套接字上发送 2 个字节的应用程序数据 阻塞 但发送调用在下面的最后一个实例中被阻塞超过 40 秒 2012 06 13 12 02 46 653417 信息 发送前 2012 06 13 12 02 46 653457 信
  • 用于获取特定用户 ID 和进程数的 Bash 脚本

    我需要 bash 脚本来计算特定用户或所有用户的进程 我们可以输入 0 1 或更多参数 例如 myScript sh root deamon 应该像这样执行 root 92 deamon 8 2 users has total proces
  • 从哪里获取 iostream.h

    我正在尝试在 Linux 中做一些事情 但它抱怨找不到 iostream h 我需要安装什么才能获取此文件 这个标准头的正确名称是iostream没有扩展名 如果您的编译器仍然找不到它 请尝试以下操作 find usr include na
  • 如何使用 VSCode 调试 Linux 核心转储?

    我故意从我使用 VSCode 编写的 C 应用程序生成核心转储 我不知道如何调试核心转储 有没有人愿意分享这方面的经验 更新 我相信我现在已经可以使用了 我为核心文件创建了第二个调试配置 我需要添加指向生成的转储文件的 coreDumpPa
  • Unix 中的访问时间是多少

    我想知道访问时间是多少 我在网上搜索但得到了相同的定义 读 被改变 我知道与touch我们可以改变它 谁能用一个例子来解释一下它是如何改变的 有没有办法在unix中获取创建日期 时间 stat结构 The stat 2 结构跟踪所有文件日期

随机推荐

  • linux c语言高级编程-目录操作

    目录操作总共有以下几个函数 xff1a 1 创建目录 int mkdir const char pathname mode t mode 2 删除目录 int rmdir const char pathname 3 查看目录状态 int s
  • BeagleBone Black使用(一):狗板简介

    前言 BeagleBone 与 Arduino 和 Raspberry Pi xff08 树莓派 xff09 可以说是目前应用最广泛的三大嵌入式开源平台 而 BeagleBone 在一定程度上可视为融合了 Arduino 与树莓派的优点 x
  • 慧数汽车大数据分析:车市竞争将由打造爆款向构建“产品矩阵”转型

    在车企只要完成年销量三十万辆的目标时 xff0c 只需认认真真培育出一款爆款车就足够了 xff0c 如哈弗H6 完成年销量50万辆的目标时 xff0c 只需认认真真培育出一两款爆款车就足够了 xff0c 如哈弗H6 43 哈弗H2 但为什么
  • 4.10 Python tuple元组详解

    元组 xff08 tuple xff09 是 Python 中另一个重要的序列结构 xff0c 和列表类似 xff0c 元组也是由一系列按特定顺序排序的元素组成 元组和列表 xff08 list xff09 的不同之处在于 xff1a 列表
  • 使用ROS和RealSense直接获取点云

    点云获取 Realsense获取内参创建ROS工作环境创建ROS工作包package向package中添加cpp代码catkin make编译失败失败1 使用ROS订阅节点 xff08 rgb和depth xff09 ROS包安装升级Rea
  • 集成单点登录

    随着现在的系统越来越多 xff08 OA考勤 xff0c 学生宿舍管理等等 xff09 在使用中是不是还在为一次一次的登录而烦恼 xff1f 或者忘了密码而尴尬 xff0c 现在 xff0c 有一个好东西来解决这个问题了 那就是单点登录 单
  • PID算法入门与C语言代码实现

    PID算法的入门理解以及C代码实现 在结束了自控原理的学习后 xff0c 了解到PID算法是一种万能算法 xff0c 在课设中也是经常使用到的一种算法 xff0c 所以想具体的来进行以下总结与学习 xff0c 如果有错漏的地方 xff0c
  • 【Ubuntu18.04安装px4+mavros(解决mavros报错问题)】

    Ubuntu18 04安装px4 43 mavros xff08 解决mavros报错问题 xff09 安装ros melodic重新安装gazebo9 19安装mavros安装px4 我的电脑为联想R7000P2021款 xff0c 之前
  • 嵌入式面试题3

    1 讲一下STM32时钟系统 时钟系统类似于脉搏 xff0c 控制着CPU的命脉 xff0c STM32的时钟源又不像51的时钟源那么单一 xff0c 因为STM32的MCU较为复杂 xff0c 且外设较多 xff0c 并不是所有的外设都需
  • 将 linuxmint 20.2 设置成 mac 主题

    将 linuxmint 20 2 设置成 mac 主题 1 安装Adapta Nokto主题2 安装Numix Circle图标3 安装plank4 设置主题和图标5 设置字体 使用 vmware 安装 LinuxMint20 2 并打造
  • [转载][paper]Threat of Adversarial Attacks on Deep Learning in Computer Vision: A Survey

    文章目录 摘要 深度学习是当前人工智能崛起的核心 在计算机视觉领域 xff0c 它已经成为从自动驾驶汽车到监控和安全等各种应用的主力 虽然深度神经网络在解决复杂问题方面取得了惊人的成功 通常超出了人类的能力 xff0c 但最近的研究表明 x
  • [paper]Feature Squeezing: Detecting Adversarial Examples in Deep Neural Networks

    本文提出了两种特征压缩方法 xff1a 减少每个像素的颜色位深度使用空间平滑来减少各个像素之间的差异 特征压缩通过将与原始空间中许多不同特征向量相对应的样本合并为单个样本 xff0c 从而减少了对手可用的搜索空间 通过将DNN模型对原始输入
  • C# List集合查找删除指定数据

    C List集合查找删除指定数据 文章目录1 实体类2 操作第一个负荷条件数据3 操作所有符合条件数据4 优质源码 文章目录 1 实体类 public class FaultLevelModel public string LBWJ get
  • 【论文阅读】AM-Softmax:Additive Margin Softmax for Face Verification. 1801.05599.【损失函数设计】

    原文链接 xff1a https blog csdn net weixin 43154149 article details 122611784 文章目录 1 四个问题2 论文简介1 Introduction xff08 相关工作 xff1
  • MobaXterm连接出现 Network error: Connection timed out 问题解决

    MobaXterm连接出现 Network error Connection timed out xff1a 接前文 xff1a CentOS安装 点此查看文章 xff0c 安装之后的SSH连接 xff1a 解决思路如下 xff1a 1 检
  • 撰写论文时如何复制参考文献公式----Mathpix及Mathtype教程

    同学们好啊 xff0c 我们在写论文时常常需要使用一些复杂的公式 xff0c 自己对着敲又费时费力 xff0c 那么如何才能讲文献中或者书本上的公式复制在自己的文章中嘞 xff1f 阿阮分享两个公式神器 xff0c 配合使用效果更好哈 xf
  • 驱动及驱动开发的简单理解

    一直对驱动有着强烈的好奇心 xff0c 怎奈工作始终与其无缘 xff0c 且未来也不大可能接触驱动 因此 xff0c 今天用了一些时间 xff0c 去简单的了解了一下驱动及驱动开发 如果有错误的理解 xff0c 请予以指正 xff0c 不胜
  • Mac ping IP+端口

    MacOS中ping IP 43 端口 nc vz w 2 192 168 1 1 8080 windows下 telnet 192 168 1 1 8080
  • 对文件夹下所有灰度图片进行像素值的修改

    最近在跑UNet训练的时候 xff0c 想用自己的数据集做训练 xff0c 发现数据集无法加载进去 xff0c 对比了一下源码所使用的数据集 xff0c 发现是gt的像素值不对导致的 xff0c 为了省事就写了个修改gt像素值的小脚本 im
  • Linux操作系统-信号量

    信号量也属于一种进程间通信的机制 xff0c 与其他的进程间通信不同 xff0c 信号量不是用来传输数据的 xff0c 而是用来进程间同步与互斥 除此之外 xff0c 信号量还可以实现线程间的互斥 信号量是什么 xff1f 信号量的本质是一