日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

进程间通信的方式(四):信号量

發布時間:2025/4/16 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程间通信的方式(四):信号量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ???? ?信號量(semaphore)是一種用于提供不同進程之間或者一個給定的不同線程間同步手段的原語。信號量多用于進程間的同步與互斥,簡單的說一下同步和互斥的意思:

同步:處理競爭就是同步,安排進程執行的先后順序就是同步,每個進程都有一定的先后執行順序。

互斥:互斥訪問不可共享的臨界資源,同時會引發兩個新的控制問題(互斥可以說是特殊的同步)。

競爭:當并發進程競爭使用同一個資源的時候,我們就稱為競爭進程。

?? ??? ?共享資源通常分為兩類:一類是互斥共享資源,即任一時刻只允許一個進程訪問該資源;另一類是同步共享資源,即同一時刻允許多個進程訪問該資源;信號量是解決互斥共享資源的同步問題而引入的機制。

1.概述:

?? ??? ?簡單說一下信號量的工作機制(因為真的很簡單),可以直接理解成計數器(當然其實加鎖的時候肯定不能這么簡單,不只只是信號量了),信號量會有初值(>0),每當有進程申請使用信號量,通過一個P操作來對信號量進行-1操作,當計數器減到0的時候就說明沒有資源了,其他進程要想訪問就必須等待(具體怎么等還有說法,比如忙等待或者睡眠),當該進程執行完這段工作(我們稱之為臨界區)之后,就會執行V操作來對信號量進行+1操作。

臨界區:臨界區指的是一個訪問共用資源(例如:共用設備或是共用存儲器)的程序片段,而這些共用資源又無法同時被多個線程訪問的特性。

臨界資源:只能被一個進程同時使用(不可以多個進程共享),要用到互斥。

?? ??? ?我們可以說信號量也是進程間通信的一種方式,比如互斥鎖的簡單實現就是信號量,一個進程使用互斥鎖,并通知(通信)其他想要該互斥鎖的進程,阻止他們的訪問和使用。

?

當有進程要求使用共享資源時,需要執行以下操作:

1.系統首先要檢測該資源的信號量;

2.若該資源的信號量值大于0,則進程可以使用該資源,此時,進程將該資源的信號量值減1;

3.若該資源的信號量值為0,則進程進入休眠狀態,直到信號量值大于0時進程被喚醒,訪問該資源;

???????當進程不再使用由一個信號量控制的共享資源時,該信號量值增加1,如果此時有進程處于休眠狀態等待此信號量,則該進程會被喚醒。


2.信號量的具體結構

每個信號量集都有一個與其相對應的結構,該結構定義如下:

/* Data structure describing a set of semaphores. */ struct semid_ds { struct ipc_perm sem_perm; /* operation permission struct */ struct sem *sem_base; /* ptr to array of semaphores in set */ unsigned short sem_nsems; /* # of semaphores in set */ time_t sem_otime; /* last-semop() time */ time_t sem_ctime; /* last-change time */ }; /* Data structure describing each of semaphores. */ struct sem { unsigned short semval; /* semaphore value, always >= 0 */ pid_t sempid; /* pid for last successful semop(), SETVAL, SETALL */ unsigned short semncnt; /* # processes awaiting semval > curval */ unsigned short semzcnt; /* # processes awaiting semval == 0 */ };

信號量集的結構圖如下所示:

3.代碼實現信號量

使用信號量實現生產者消費者模式

#include "stdafx.h" #include <stdio.h> #include <pthread.h> #include <sched.h> #include <semaphore.h> #include <conio.h> #include <ctype.h> #include <signal.h> #include <iostream>#include<Windows.h> using namespace std; #pragma comment(lib,"pthreadVC2.lib") #define N 5 //消費者或者生產者的數目 #define M 10 //緩沖數目int productin = 0; //生產者放置產品的位置 int prochaseout = 0; //消費者取產品的位置int buff[M] = {0}; //緩沖區初始化為0,開始時沒有產品。sem_t empty_sem; // 同步信號量,當滿的時候阻止生產者放產品。 sem_t full_sem; //同步信號量,當沒有產品的時候阻止消費者消費。pthread_mutex_t mutex; //互斥信號量,一次只有一個線程訪問緩沖區。int product_id = 0; //生產者id int prochase_id = 0; //消費者idvoid SignalExit(int signo) {printf("程序退出%d\n",signo);return; }void PrintProduction() {printf("此時的產品隊列為::");for(int i = 0; i < M; i++ ){printf("%d ",buff[i]);}printf("\n\n"); }//生產者方法 void* Product(void* pramter) {int id = ++product_id;while(1){Sleep(5000); //毫秒sem_wait(&empty_sem); //給信號量減1操作pthread_mutex_lock(&mutex);productin = productin % M;printf("生產者%d在產品隊列中放入第%d個產品\n\n",id,productin+1);buff[productin] = 1;PrintProduction();++productin;pthread_mutex_unlock(&mutex); //釋放互斥量對象sem_post(&full_sem); //給信號量的值加1操作} }//消費者方法/// void* Prochase( void* pramter ) {int id = ++prochase_id;while(1){Sleep(7000);sem_wait(&full_sem);pthread_mutex_lock(&mutex);prochaseout = prochaseout % M;printf("消費者%d從產品隊列中取出第%d個產品\n\n",id,prochaseout+1);buff[prochaseout] = 0;PrintProduction();++prochaseout;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);} }int main() {cout << "生產者和消費者數目都為5,產品緩沖區為10,生產者每2秒生產一個產品,消費者每5秒消費一個產品" << endl << endl;pthread_t productid[N];pthread_t prochaseid[N];int ret[N];//初始化信號量int seminit1 = sem_init(&empty_sem,0,M);int seminit2 = sem_init(&full_sem,0,0);if( seminit1 != 0 && seminit2 != 0 ){printf("sem_init failed !!!\n");return 0;}//初始化互斥信號量int mutexinit = pthread_mutex_init(&mutex,NULL);if( mutexinit != 0 ){printf("pthread_mutex_init failed !!\n");return 0;}//創建n個生產者線程for(int i = 0; i < N; i++ ){ret[i] = pthread_create( &productid[i], NULL,Product,(void*)(&i) );if( ret[i] != 0 ){printf("生產者%d線程創建失敗!\n",i);return 0;}}//創建n個消費者線程for(int j = 0; j < N; j++ ){ret[j] = pthread_create(&prochaseid[j],NULL,Prochase,NULL);if( ret[j] != 0 ){printf("消費者%d線程創建失敗\n",j);return 0;}}///等待線程被銷毀///for( int k = 0; k < N; k++ ){printf("銷毀線程\n");pthread_join(productid[k],NULL);pthread_join(prochaseid[k],NULL);}return 0; }

?

?

?

總結

以上是生活随笔為你收集整理的进程间通信的方式(四):信号量的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。