首页 > 系统相关 >Linux:线程同步之信号量

Linux:线程同步之信号量

时间:2024-08-07 15:55:57浏览次数:16  
标签:Node 共享资源 int 信号量 线程 Linux sem

信号量

(1)What(什么是信号量)

提供一种计数器的方式控制对共享资源的访问;当计数器大于0时,请求资源成功并计数器-1;当计数器小于0时,线程阻塞,等待其它线程执行signal(V操作)唤醒它

(2)Why(信号量的作用)

  • 实现线程的同步与互斥:通过信号量的设计,可以实现对共享资源的串行访问
  • 实现线程的等待与通知机制:当信号量小于0时,当前线程将被阻塞;当信号量大于0时,会唤醒一个阻塞在信号量上的线程

(3)How(如何使用信号量实现线程同步)

step01:创建信号量

可以看作是创建一个信号量对象

sem_t sem; 

step02:初始化信号量

可以看作是对信号量对象的一个初始化,这一过程会给信号量的计数器赋予一个初始值

int sem_init(sem_t *sem, int pshared, unsigned int value); 
  • 参数sem:被初始化的信号量对象
  • 参数pshared:默认为0,表示信号量用于线程同步;其它表示信号量用于进程同步
  • 参数value:表示信号量的数量,常用用于表示共享资源的数量
  • 返回值:成功返回0,失败返回-1,并设置错误码

step03:请求资源

请求获取共享资源,此时信号量的计数器减1;如果信号量小于1,请求失败,线程阻塞,直到信号量满足条件时解除阻塞

int sem_wait(sem_t *sem); 
  • 参数sem:请求共享资源,如果sem中的计数器大于0,则请求成功,否则线程阻塞
  • 返回值:成功返回0,失败返回-1,并设置错误码

step04:释放资源

释放共享资源,此时信号量的计数器加1,此时会唤醒一个等待该共享资源的线程

int sem_post(sem_t *sem);

  • 参数sem:释放共享资源,sem中的计数器+1
  • 返回值:成功返回0,失败返回-1,并设置错误码
    step05:销毁信号量

本质就是释放信号量对象的内存空间

int sem_destroy(sem_t *sem); 
  • 参数sem:将要被销毁的信号量对象
  • 返回值:成功返回0,失败返回-1,并设置错误码

(4)代码实例

以下代码是对共享资源的互斥访问,共享资源的个数为5

#include <semaphore.h>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex;
sem_t semProc;
sem_t semComu;
struct Node{
	int iVal;
	Node * ptrNext;
	static int iSize;
};
int Node::iSize = 0;
Node * head = NULL;
void *produce(void  *arg){
	int i = 0;
	while(1){
		sem_wait(&semProc);
		pthread_mutex_lock(&mutex);
		int iVal = i;
		Node *node = new Node;
		node->iVal = iVal;
		node->ptrNext = head->ptrNext;
		head->ptrNext = node;
		Node::iSize++;
		cout<<"Producing "<<iVal<<"("<<Node::iSize<<")"<<endl;
		pthread_mutex_unlock(&mutex);
		sem_post(&semComu);
		++i;
		sleep(1);
	}
}
void *consume(void *arg){
	while(1){
		sem_wait(&semComu);
		pthread_mutex_lock(&mutex);
		if(head->ptrNext!=NULL)
		{
			cout<<"Comsuing "<<head->ptrNext->iVal;
			Node *ptr = head->ptrNext;
			head->ptrNext = ptr->ptrNext;
			Node::iSize--;
			delete ptr;
			cout<<"("<<Node::iSize<<")"<<endl;
			ptr = 0;
		}
		pthread_mutex_unlock(&mutex);
		sem_post(&semProc);
		sleep(2);
	}
	return NULL; 
}
int main()
{
	head = new Node; 
	pthread_t tidProc,  tidComu; 
	sem_init(&semProc, 0, 5); 
	sem_init(&semComu, 0, 0); 
	pthread_create(&tidProc,  NULL,  produce,  NULL); 
	pthread_create(&tidComu, NULL, conmuse, NULL); 
	pthread_join(tidProc, NULL); 
	pthread_join(tidComu, NULL); 
	return 0; 
}

标签:Node,共享资源,int,信号量,线程,Linux,sem
From: https://blog.csdn.net/qq_42279379/article/details/140964302

相关文章

  • Python安装教程(含MacOS&&Linux系统)
    Python安装教程Windows用户访问Python官网:WelcometoPython.org 打开下载好的安装包根据提示安装   Pip换源(系统级别)(注:Pip在3.4以上的版本才支持,3.4之前的版本可以在cmd中输入 easy_installpip 下载pip)1.为什么要换源?Python安装......
  • linux中的find命令
    简介find命令是Linux系统中最重要和最常用的命令之一。搜索和查找与参数匹配的文件和目录的命令。查找可以在各种条件下使用,您可以通过权限,用户,组,文件类型,日期,大小等可能的条件查找文件。语法find[起始目录]寻找条件操作说明:find命令从指定的起始目录开始,递归地搜索其各......
  • Linux服务器配置SHH免密互通
    服务器A172.25.11.11,服务器B172.25.11.12在服务器A上配置假设服务器A的IP地址为172.25.11.11,我们将在这台服务器上生成密钥对并将公钥复制到服务器B上。生成密钥对:打开终端,执行以下命令生成密钥对。在生成过程中,你可以选择保留默认路径和设置空密码以简化使用,也可......
  • Linux三剑客之grep
    介绍Linuxgrep(globalregularexpression)命令用于查找文件里符合条件的字符串或正则表达式。grep是行过滤工具,用于根据关键字进行行过滤,包含关键字的行过滤出来。根据模式去搜索文本,并将符合模式的文本行显示出来。语法grep[options]pattern[files]options:选项参数......
  • linux与windows环境下qt程序打包教程
    一、演示环境qt5.14.2二、Linux2.1关联依赖文件2.1.1下载打包工具在Windows环境下可以使用QtCreator自带的官方工具进行打包,而Linux环境下没有官方工具,需要借助第三方工具才能打包。如:linuxdeployqt、CQtDeployer、AppImageKit,甚至是自己编写shell将依赖导入指定目录......
  • Linux内核学习—— 1内核体系结构
    一内核体系结构1内核模式与体系结构2内核中断概括3进程管理概括二内核源码结构三内核引导程序操作系统结构:用户应用程序操作系统服务层内核(文件系统,内存管理,进程管理,驱动管理)硬件系统驱动操作系统工作方式:把做操作系统从用户态切换到内核态(用户应用程序到内核流......
  • Linux服务器SSH远程密钥免密登录
    说明业务场景中经常需要进行跨服务器的操作,即从一台服务器上登录到另外一台服务器,默认情况下,SSH远程登录时需要输入远程服务器密码。当需要在可信任的服务器之间进行频繁或自动化的操作时,输入密码就会带来不便。本文介绍如何实现SSH远程免密登录。服务器信息假设有2台服......
  • Nessus Professional 10.8.0 Auto Installer for RHEL 9/AlmaLinux 9/Rocky Linux 9
    NessusProfessional10.8.0AutoInstallerforRHEL9/AlmaLinux9/RockyLinux9发布Nessus试用版自动化安装程序,支持macOSSonoma、RHEL9和Ubuntu24.04请访问原文链接:https://sysin.org/blog/nessus-auto-install-for-rhel-9/,查看最新版。原创作品,转载请保留出处。N......
  • Linux安装Docker
    安装前问题1.新安装的CentOS在首次登录时出现需要创建一个新用户的界面Ctrl+Alter+F2新建一个命令行桌面,在这个界面可以使用root账号密码登录在命令行界面执行以下命令,即可跳过该步骤yumremovegnome-initial-setupinit3init52.无法正常显示ipv4地址1.进入存放网......
  • linux进程管理相关命令
    一、进程的概念程序的一次执行就是一个进程 程序的两次执行就产生了p1和p2进程 二、使用ps命令查看进程显示进程(process)的动态1、语法:            ps[options]2、常见的参数:    -A 列出所有的行程       -w ......