Linux操作系统-信号量

article/2025/11/7 6:14:06

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

信号量是什么?

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

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

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

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

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

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

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

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

P操作

相当于count--;

P(){lock();if(count)count--;elsewait(); // 阻塞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;
}


http://chatgpt.dhexx.cn/article/qAGkhL7Q.shtml

相关文章

Linux·信号量全解

目录 信号量 进程间 【无名信号量完成 有血缘关系的进程间 互斥】 知识点2【有名信号量 没有血缘进程互斥】 1、创建一个有名信号量 2、信号量的关闭&#xff1a; 3、信号量文件的删除 4、P操作 sem_wait V操作sem_post 销毁信号量sem_destroy 知识点3【有名信号量 没…

Linux-----信号量

信号量 信号量原理信号量概念信号量函数基于环形队列的生产消费模型空间和数据资源生产者和消费者申请、释放信号量模拟实现基于环形队列的生产者消费者模型 信号量原理 之前我们知道被多个执行流同时访问的公共资源叫做临界资源&#xff0c;而临界资源不保护的话会造成数据不…

Linux信号量

文章目录 POSIX信号量信号量的原理信号量的概念信号量函数 二元信号量模拟实现互斥功能基于环形队列的生产消费模型空间资源和数据资源生产者和消费者申请和释放资源必须遵守的两个规则代码实现信号量保护环形队列的原理 POSIX信号量 信号量的原理 我们将可能会被多个执行流同…

Linux —— 信号量

目录 一、POSIX信号量 1. 什么是信号量 2. 信号量的基本原理 二、与信号量相关的操作 1. 初始化信号量 2. 销毁信号量 3. 等待信号量 4. 发布信号量 三、基于环形队列的生产者消费者模型 1. 空间资源和数据资源 2. 生产者和消费者申请和释放资源 四、模拟实现基于…

Double取值intValue()与doubleValue()之参数缺省

Double调用intValue()是四舍五入向下取整。 调用doubleValue()才是取double真实值。

java.lang.NullPointerException: Attempt to invoke virtual method ‘int java.lang.Integer.intValue()‘

问题 对于PreparedStatement 对象设置参数时&#xff0c; 提示该错误; java.lang.NullPointerException: Attempt to invoke virtual method ‘int java.lang.Integer.intValue()’ 具体问题 2022-09-06 21:28:10.695 11368-11755/com.example.electronicmall E/AndroidRunt…

IntValue()方法 和 ValueOf()方法

intValue() 1.intValue()是java.lang.Number类的方法&#xff0c;Number是一个抽象类。Java中所有的数值类都继承它。也就是说&#xff0c;不单是Integer有intValue方法&#xff0c;Double&#xff0c;Long等都有此方法。 2.此方法的意思是&#xff1a;输出int数据。每个数值类…

Double取值intValue()与doubleValue()

描述一个之前没注意&#xff0c;手误造成的bug。 可以看出&#xff0c;Double调用intValue()结果类似于RoundingMode.DOWN。 调用doubleValue()才是取double真实值。

java中valueof_JAVA中intValue()和ValueOf()什么意思,还有Value什么意思

展开全部 intValue()和ValueOf()是数据类62616964757a686964616fe59b9ee7ad9431333366306538型转化的两个方法。 intValue() 如Integer类型&#xff0c;就会有intValue()方法&#xff0c;意思是说&#xff0c;把Integer类型转化为Int类型。 valueOf() 如String就有valueOf()方法…

IDEA告警:Unnecessary unboxing ‘xxx.intValue()‘

显式编码拆箱已包装的原始数值。在Java5及以上的版本&#xff0c;拆箱是不必要的&#xff0c;可以安全地删除。那么 JDK5 到底做了啥&#xff1f; 自动装箱&#xff08;auto-boxing&#xff09;与自动拆箱&#xff08;auto-unboxing&#xff09; Java语言的基本类型都有包装&…

latex自定义插入空行或者空格

空行有几种方法&#xff1a; 1.~\\ 2.\\[行距] 例如&#xff1a;\\[3pt] 最后&#xff0c;我的选择是&#xff1a; \vspace*{n\baselineskip}空格&#xff1a;

latex中加入空白行的一种方法

在两行文字中间加入“~\\”就可以达到空行的目的了 如图所示&#xff0c;上面是加入“~\\”&#xff0c;下图是得到的结果

latex句首缩进空格

有时候想要再句首加空格&#xff0c;但是会被自动忽略&#xff0c;于是可以使用命令 \hspace*{0.6cm} 例如&#xff1a; $initialize the initial solutions w,precision,max_iters,\\ while (w< precision) and (iters < max_iters):\\\hspace*{0.6cm} grad \gets \…

LaTeX数学公式中的空格

两个quad空格 a \qquad b 两个m的宽度 quad空格 a \quad b 一个m的宽度 大空格 a\ b 1/3m宽度 中等空格 a\;b 2/7m宽度 小空格 a\,b 1/6m宽度 没有空格 ab 紧贴 a\!b 缩进1/6m宽度 \quad、1em、em、m代表当前字体下接近字符‘M’的宽度&#xff08;approximately the …

Latex空格

Latex空格分许多种&#xff0c;分别有&#xff1a; 源代码 \documentclass[UTF8]{ctexart}\begin{document}\begin{tabular}{|l|l|l|l|} \hline 类别 & 用法 & 含义 & 效果\\ \hline 两个quad & a$\backslash$qquad b & 两个m的宽度 & a\qquad b \\ \h…

Latex 公式中空格添加

转自&#xff1a;https://blog.csdn.net/bennyfun79/article/details/15500575 两个quad空格a \qquad b两个m的宽度quad空格a \quad b一个m的宽度大空格a\ b1/3m宽度中等空格a\;b2/7m宽度小空格a\,b1/6m宽度没有空格ab 紧贴a\!b缩进1/6m宽度

latex中的对与错(对号√与叉号×)、空格

转载 LaTeX 对号和错号_Xovee的博客-CSDN博客_latex对号错号 【转载】LaTeX中的空格汇总_AXYZdong的博客-CSDN博客_latex空格符号怎么打出来 空格 对号√ 错号 代码 \documentclass{article} \usepackage[utf8]{inputenc} \usepackage{url} \usepackage{booktabs} \usepackag…

LaTex中输入空格以及换行

1. 使用\ 表示空格 以及调整空格的大小 quad空格a \qquad b两个m的宽度quad空格a \quad b一个m的宽度大空格a\ b1/3m宽度中等空格a\;b2/7m宽度小空格a\,b1/6m宽度没有空格ab 紧贴a\!b缩进1/6m宽度 \quad、1em、em、m代表当前字体下接近字符‘M’的宽度。 2.使用\\ 表示换行