操作系統 實驗29 同步與互斥

1、并發線程同步與互斥

源程序:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
int num=30,count=10;
pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER; 
void *sub1(void *arg) {int i = 0,tmp;for (; i <count; i++){pthread_mutex_lock(&mylock);    			tmp=num-1;usleep(13);num=tmp;								pthread_mutex_unlock(&mylock);	        		printf("線程1 num減1后值為: %d\n",num);}return ((void *)0);
}
void *sub2(void *arg){int i=0,tmp;for(;i<count;i++){pthread_mutex_lock(&mylock);tmp=num-1;usleep(31);num=tmp;pthread_mutex_unlock(&mylock);printf("線程2 num減1后值為: %d\n",num);}return ((void *)0);
}
int main(int argc, char** argv) {pthread_t tid1,tid2;int err,i=0,tmp;void *tret;err=pthread_create(&tid1,NULL,sub1,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}
err=pthread_create(&tid2,NULL,sub2,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}for(;i<count;i++){pthread_mutex_lock(&mylock);     			tmp=num-1;usleep(5);	num=tmp;		pthread_mutex_unlock(&mylock); printf("main num減1后值為: %d\n",num);}printf("兩個線程運行結束\n");err=pthread_join(tid1,&tret);
if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 1 exit code %d\n",(int)tret);err=pthread_join(tid2,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 2 exit code %d\n",(int)tret);return 0;
}

編譯鏈接命令:gcc threadmutex.c -o threadmutex -lpthread

運行命令:./threadmutex

交互與結果:

2、生產者-消費者同步與互斥試驗

源程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>
#define Maxbuf 10		//緩沖單元數目
#define TimesOfOp 10		//生產者、消費者循環讀寫緩沖區的次數
#define true 1
#define false 0
#define historynum 100	//生產者、消費者讀寫歷史記錄數目
struct Circlebuf	//循環緩沖隊列結構
{int read; 			//讀指針int write; 		//寫指針int buf[Maxbuf]; 	//緩沖區
} circlebuf;
sem_t mutex;			//互斥信號量
sem_t empty; 			//空白緩沖區同步信號量
sem_t full; 			//滿緩沖區同步信號量
char writehistory[historynum][30];//寫歷史
char readhistory[historynum][30];//讀歷史
int writehistorycount=0;		//寫歷史計數器
int readhistorycount=0; 		//讀歷史計數器
char history[historynum][30];	//緩沖區操作歷史
int historycount=0;		//緩沖區操作歷史計數器
void writeCirclebuf(struct Circlebuf *circlebuf,int *value) //向緩沖區中寫一個值
{circlebuf->buf[circlebuf->write]=(*value);sleep(1);							circlebuf->write=(circlebuf->write+1)%Maxbuf; 
}
int readCirclebuf(struct Circlebuf *circlebuf)
{int value=0;value=circlebuf->buf[circlebuf->read];		sleep(1);								circlebuf->buf[circlebuf->read]=0; 			circlebuf->read=(circlebuf->read+1)%Maxbuf; 	return value;
}
void sigend(int sig)
{exit(0);
}
void * productThread(void *i)
{int *n=(int *)i;int t=TimesOfOp;int writeptr;while(t--){	sem_wait(&empty);sem_wait(&mutex);writeCirclebuf(&circlebuf,n);if(circlebuf.write>0) writeptr=circlebuf.write-1;else writeptr= Maxbuf-1;sprintf(writehistory[writehistorycount++],"生產者%d:緩沖區%d=%d", *n,writeptr,*n);sprintf(history[historycount++],"生產者%d:緩沖區%d=%d\n", *n,writeptr, *n);sem_post(&mutex);sem_post(&full);sleep(1);}
}
void * consumerThread(void *i)
{int *n=(int *)i;int t=TimesOfOp;						int value=0;							int readptr;							while(t--){sem_wait(&full);						sem_wait(&mutex);value=readCirclebuf(&circlebuf);			if(circlebuf.read>0) readptr=circlebuf.read-1;	else readptr= Maxbuf-1;sprintf(readhistory[readhistorycount++], "消費者%d:緩沖區%d=%d\n", *n,readptr,value);sprintf(history[historycount++],"消費者%d:緩沖區%d=%d\n", *n,readptr,value);sem_post(&mutex);						sem_post(&empty);						sleep(1);							}
}
int main()
{int i,max;int ConsNum=0,ProdNum=0,ret;sem_init(&mutex,0,1);sem_init(&empty,0,Maxbuf);sem_init(&full,0,0);	signal(SIGINT, sigend);signal(SIGTERM, sigend);circlebuf.read=circlebuf.write=0;for(i=0;i<Maxbuf;i++)circlebuf.buf[i]=0;printf("請輸入生產者線程的數目 :");scanf("%d",&ProdNum);int *pro=(int*)malloc(ProdNum*sizeof(int));pthread_t *proid=(pthread_t*)malloc(ProdNum*sizeof(pthread_t));printf("請輸入消費者線程的數目 :");scanf("%d",&ConsNum);int *con=(int*)malloc(ConsNum*sizeof(int));pthread_t *conid=(pthread_t*)malloc(ConsNum*sizeof(pthread_t));for(i=1;i<=ConsNum;i++){con[i-1]=i;ret=pthread_create(&conid[i],NULL,consumerThread,(void *)&con[i-1]);if(ret!=0){printf("Create thread error");exit(1);}}for(i=1;i<=ProdNum;i++){pro[i-1]=i;ret=pthread_create(&proid[i],NULL,productThread,(void *)&pro[i-1]);if(ret!=0){printf("Create thread error");exit(1);}}sleep((ConsNum+ ProdNum)*10);if (writehistorycount>readhistorycount) max=writehistorycount;else max=readhistorycount;for(i=0;i<max;i++)if ((i<writehistorycount) && (i<readhistorycount))printf("%s | %s\n",writehistory[i],readhistory[i]);else if (i<writehistorycount)printf("%s | %s\n",writehistory[i]," ");else 	printf("%s | %s\n"," ",readhistory[i]);printf("*************緩沖池的操作歷史為:******************\n");for(i=0;i<historycount;i++)  printf("%s",history[i]);sem_destroy(&mutex);	sem_destroy(&empty);sem_destroy(&full);
}

編譯鏈接命令:gcc pc1.c -o pc1 -lpthread

運行命令:./pc1

交互與結果:

3、生產者-消費者未加同步與互斥機制的運行試驗

源程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#define Maxbuf 10       //緩沖單元數目
#define TimesOfOp 10    //生產者、消費者循環讀寫緩沖區的次數
#define true 1
#define false 0
#define historynum 100  //生產者、消費者讀寫歷史記錄數目
struct Circlebuf    //循環緩沖隊列結構
{int read;            //讀指針int write;       //寫指針int buf[Maxbuf];    //緩沖區
} circlebuf;char writehistory[historynum][30];//寫歷史
char readhistory[historynum][30];//讀歷史
int writehistorycount=0;        //寫歷史計數器
int readhistorycount=0;         //讀歷史計數器
char history[historynum][30];    //緩沖區操作歷史
int historycount=0;        //緩沖區操作歷史計數器void writeCirclebuf(struct Circlebuf *circlebuf,int *value) //向緩沖區中寫一個值
{circlebuf->buf[circlebuf->write]=(*value);sleep(1);                           circlebuf->write=(circlebuf->write+1)%Maxbuf; 
}
int readCirclebuf(struct Circlebuf *circlebuf)
{int value=0;value=circlebuf->buf[circlebuf->read];        sleep(1);                                circlebuf->buf[circlebuf->read]=0;            circlebuf->read=(circlebuf->read+1)%Maxbuf;     return value;
}void sigend(int sig)
{exit(0);
}void * productThread(void *i)
{int *n=(int *)i;int t=TimesOfOp;int writeptr;while(t--){   writeCirclebuf(&circlebuf,n);if(circlebuf.write>0) writeptr=circlebuf.write-1;else writeptr= Maxbuf-1;sprintf(writehistory[writehistorycount++],"生產者%d:緩沖區%d=%d", *n,writeptr,*n);sprintf(history[historycount++],"生產者%d:緩沖區%d=%d\n", *n,writeptr, *n);sleep(1);}
}void * consumerThread(void *i)
{int *n=(int *)i;int t=TimesOfOp;                        int value=0;                            int readptr;                            while(t--){value=readCirclebuf(&circlebuf);            if(circlebuf.read>0) readptr=circlebuf.read-1;    else readptr= Maxbuf-1;sprintf(readhistory[readhistorycount++], "消費者%d:緩沖區%d=%d\n", *n,readptr,value);sprintf(history[historycount++],"消費者%d:緩沖區%d=%d\n", *n,readptr,value);sleep(1);}
}int main()
{int i,max;int ConsNum=0,ProdNum=0,ret;circlebuf.read=circlebuf.write=0;for(i=0;i<Maxbuf;i++)circlebuf.buf[i]=0;printf("請輸入生產者線程的數目 :");scanf("%d",&ProdNum);int *pro=(int*)malloc(ProdNum*sizeof(int));pthread_t *proid=(pthread_t*)malloc(ProdNum*sizeof(pthread_t));printf("請輸入消費者線程的數目 :");scanf("%d",&ConsNum);int *con=(int*)malloc(ConsNum*sizeof(int));pthread_t *conid=(pthread_t*)malloc(ConsNum*sizeof(pthread_t));for(i=1;i<=ConsNum;i++){con[i-1]=i;ret=pthread_create(&conid[i],NULL,consumerThread,(void *)&con[i-1]);if(ret!=0){printf("Create thread error");exit(1);}}for(i=1;i<=ProdNum;i++){pro[i-1]=i;ret=pthread_create(&proid[i],NULL,productThread,(void *)&pro[i-1]);if(ret!=0){printf("Create thread error");exit(1);}}sleep((ConsNum+ ProdNum)*10);if (writehistorycount>readhistorycount) max=writehistorycount;else max=readhistorycount;for(i=0;i<max;i++)if ((i<writehistorycount) && (i<readhistorycount))printf("%s | %s\n",writehistory[i],readhistory[i]);else if (i<writehistorycount)printf("%s | %s\n",writehistory[i]," ");else    printf("%s | %s\n"," ",readhistory[i]);printf("*************緩沖池的操作歷史為:******************\n");for(i=0;i<historycount;i++)  printf("%s",history[i]);
}

編譯鏈接命令:gcc pc2.c -o pc2?-lpthread

運行命令:./pc2

交互與結果:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21015.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21015.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21015.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

圖解 Python 編程(10) | 錯誤與異常處理

&#x1f31e;歡迎來到Python的世界 &#x1f308;博客主頁&#xff1a;卿云閣 &#x1f48c;歡迎關注&#x1f389;點贊&#x1f44d;收藏??留言&#x1f4dd; &#x1f31f;本文由卿云閣原創&#xff01; &#x1f4c6;首發時間&#xff1a;&#x1f339;2024年6月2日&…

LangChain學習之prompt格式化與解析器使用

1. 學習背景 在LangChain for LLM應用程序開發中課程中&#xff0c;學習了LangChain框架擴展應用程序開發中語言模型的用例和功能的基本技能&#xff0c;遂做整理為后面的應用做準備。視頻地址&#xff1a;基于LangChain的大語言模型應用開發構建和評估高 2. 先準備嘗試調用O…

數據結構(C):從初識堆到堆排序的實現

目錄 &#x1f31e;0.前言 &#x1f688; 1.堆的概念 &#x1f688; 2.堆的實現 &#x1f69d;2.1堆向下調整算法 &#x1f69d;2.2堆的創建&#xff08;堆向下調整算法&#xff09; ??2.2.1 向下調整建堆時間復雜度 &#x1f69d;2.3堆向上調整算法 &#x1f69d;2.…

testcontainer

在我們的項目中&#xff0c;單元測試是保證我們代碼質量非常重要的一環&#xff0c;但是我們的業務代碼不可避免的需要依賴外部的系統或服務如DB&#xff0c;redis&#xff0c;其他外部服務等。如何保證我們的測試代碼不受外部依賴的影響&#xff0c;能夠穩定的運行成為了一件比…

c++------類和對象(下)包含了this指針、構造函數、析構函數、拷貝構造等

文章目錄 前言一、this指針1.1、this指針的引出1.2、 this指針的特性 二、類的默認的六個構造函數2.1、構造函數簡述2.2構造函數 三、析構函數3.1、析構函數引出3.2、特點&#xff1a; 四、拷貝構造4.1、引入4.2、特征&#xff1a;4.3、默認拷貝構造函數 總結 前言 在本節中&a…

中國的歷史看中國的經濟發展

從中國的歷史看中國的經濟發展&#xff0c;可以發現其經歷了幾個顯著的階段&#xff0c;每個階段都有其獨特的特點和成就&#xff1a; 古代經濟&#xff1a;中國古代經濟以農業為主&#xff0c;實行井田制&#xff0c;重視水利工程的建設&#xff0c;如都江堰、靈渠等。 商業發…

Compose Multiplatform 1.6.10 發布,解釋一些小問題, Jake 大佬的 Hack

雖然一直比較關注跨平臺開發&#xff0c;但其實我很少寫 Compose Multiplatform 的內容&#xff0c;因為關于 Compose Multiplatform 的使用&#xff0c;其實我并沒在實際生產環境上發布過&#xff0c;但是這個版本確實值得一提&#xff0c;因為該版本包含&#xff1a; iOS Bet…

數據庫(15)——DQL分頁查詢

DQL分頁查詢語法 SELECT 字段列表 FROM 表名 LIMIT 起始索引&#xff0c;查詢記錄數; 注&#xff1a;起始索引從0開始&#xff0c;起始索引&#xff08;查詢頁碼-1&#xff09;*每頁顯示記錄數。 如果查詢的是第一頁&#xff0c;可以省略起始索引。 示例&#xff1a;查詢第一頁…

【考研數學】概率論如何復習?跟誰好?

概率論一定要跟對老師&#xff0c;如果跟對老師&#xff0c;考研基本上能拿滿分 概率論在考研試卷中占比并不大&#xff0c;其中&#xff1a; 高等數學&#xff0c;90分&#xff0c;約占比60%; 線性代數&#xff0c;30分&#xff0c;約占比20%; 概率論與數理統計&#xff0…

hive中的join操作及其數據傾斜

hive中的join操作及其數據傾斜 join操作是一個大數據領域一個常見的話題。歸根結底是由于在數據量超大的情況下&#xff0c;join操作會使內存占用飆升。運算的復雜度也隨之上升。在進行join操作時&#xff0c;也會更容易發生數據傾斜。這些都是需要考慮的問題。 過去了解到很…

每日5題Day15 - LeetCode 71 - 75

每一步向前都是向自己的夢想更近一步&#xff0c;堅持不懈&#xff0c;勇往直前&#xff01; 第一題&#xff1a;71. 簡化路徑 - 力扣&#xff08;LeetCode&#xff09; class Solution {public String simplifyPath(String path) {Deque<String> stack new LinkedList…

mysql的增刪查改(進階)

目錄 一. 更復雜的新增 二. 查詢 2.1 聚合查詢 COUNT SUM AVG MAX MIN 2.1.2 分組查詢 group by 子句 2.1.3 HAVING 2.2 聯合查詢/多表查詢 2.2.1 內連接 2.2.2 外連接 2.2.3 全外連接 2.2.4 自連接 2.2.5 子查詢 2.2.6 合并查詢 一. 更復雜的新增 將從表名查詢到…

自動化辦公01 smtplib 郵件?動發送

目錄 一、準備需要發送郵件的郵箱賬號 二、發送郵箱的基本步驟 1. 登錄郵箱 2. 準備數據 3. 發送郵件 三、特殊內容的發送 1. 發送附件 2. 發送圖片 3. 發送超文本內容 4.郵件模板內容 SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;即簡單郵件傳輸協議…

霍夫曼樹教程(個人總結版)

背景 霍夫曼樹&#xff08;Huffman Tree&#xff09;是一種在1952年由戴維霍夫曼&#xff08;David A. Huffman&#xff09;提出的數據壓縮算法。其主要目的是為了一種高效的數據編碼方法&#xff0c;以便在最小化總編碼長度的情況下對數據進行編碼。霍夫曼樹通過利用出現頻率…

【Qt秘籍】[009]-自定義槽函數/信號

自定義槽函數 在Qt中自定義槽函數是一個直接的過程&#xff0c;槽函數本質上是類的一個成員函數&#xff0c;它可以響應信號。所謂的自定義槽函數&#xff0c;實際上操作過程和定義普通的成員函數相似。以下是如何在Qt中定義一個自定義槽函數的步驟&#xff1a; 步驟 1: 定義槽…

<jsp:setProperty>設置有參構造函數創建的自定義對象的屬性

假設某一個類&#xff08;如TextConverter類&#xff09;有一個無參構造函數和一個有參構造函數&#xff0c;我們可以在Servlet里面先用有參構造函數自己new一個對象出來&#xff0c;存到request.setAttribute里面去。 Servlet轉發到jsp頁面后&#xff0c;再在jsp頁面上用<j…

django基于大數據+Spring的新冠肺炎疫情實時監控系統設計和實現

設計一個基于Django(后端)和Spring(可能的中間件或服務集成)的新冠肺炎疫情實時監控系統涉及多個方面,包括數據收集、數據處理、數據存儲、前端展示以及可能的中間件服務(如Spring Boot服務)。以下是一個大致的設計和實現步驟: 1. 系統架構 前端:使用Web框架(如Reac…

三種字符串的管理方式

NSString的三種實現方式 OC這個語言在不停的升級自己的內存管理&#xff0c;盡量的讓自己的 OC的字符串 問題引入 在學習字符串的過程中間會遇到一個因為OC語言更新造成的問題 例如&#xff1a; int main(int argc, const char * argv[]) {autoreleasepool {NSString* str1 …

C++核心編程類的總結封裝案例

C類的總結封裝案例 文章目錄 C類的總結封裝案例1.立方體類的封裝2.點與圓的關系的封裝3.總結 1.立方體類的封裝 在C中&#xff0c;我們可以定義一個立方體&#xff08;Cube&#xff09;類來封裝立方體的屬性和方法。立方體的屬性可能包括邊長&#xff08;side length&#xff…

【redis】set和zset常用命令

set 無序集合類型 sadd 和 smembers SADD&#xff1a;將一個或者多個元素添加到set中。注意,重復的元素無法添加到set中。 語法&#xff1a;SADD key member [member] 把集合中的元素,叫做member,就像hash類型中,叫做field類似. 返回值表示本次操作,添加成功了幾個元素. 時間復…