• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Linux C系統編程-線程取消例程和同步互斥 (三)

    線程取消例程函數

    當線程收到取消請求時,先不要馬上響應取消請求,首先執行一個線程的例程函數,執行完這個函數再響應取消。
    一般地,線程取消例程函數里面都是寫一些釋放公共資源的內容、在Linux系統,公共資源中的互斥鎖,條件變量。

    使用線程取消例程函數,是為了防止線程帶著系統公共資源一起被取消,如果帶著系統資源而退出,則其他的線程就無法再次使用該資源。

    只需要在線程中調用
    pthread_cleanup_push()
    功能: push thread cancellation clean-up handlers -> 線程取消例程函數

    routine:取消例程函數
    arg:傳遞例程函數的參數
    在這里插入圖片描述

    信號處理函數: void fun(int sig)
    線程創建: void *fun(void *arg)
    線程取消例程函數: void fun(void *)

    將取消例程函數彈棧
    void pthread_cleanup_pop(int execute);

    execute: 0 -> 不執行例程
    非0 -> 執行例程

    子線程收到主線程的退出時,不要馬上取消,而是先打印"I recv cancel!\n",再取消。

    void fun(void *arg)
    {
    	printf("I recv cancel!\n");
    }
    
    void *routine(void *arg)
    {
    	pthread_cleanup_push(fun,NULL);
    	
    	int i;
    	for(i=0;i<10;i++)
    	{
    		sleep(1);
    		printf("%d\n",i);
    	}
    	
    	pthread_exit(NULL); // 還沒來得及刪除函數就pthread_exit退出了,那么還是會執行例程函數
    	return;   			// 還沒來得及刪除函數就return退出了,那么不會執行例程函數
    	
    	sleep(1);
    	pthread_cleanup_pop(1);  //正常刪除例程函數,如果參數非0  -> 執行
    							// 正常刪除例程函數,如果是0,  -> 不執行
    }
    
    int main()
    {
    	pthread_t tid;
    	pthread_create(&tid,NULL,routine,NULL);
    	pthread_join(tid,NULL);
    	
    	return 0;
    }
    

    線程同步互斥

    使得多個線程之間處理任務時有先后順序:
    有名信號量 對象:進程
    無名信號量 對象:線程

    有名信號量

    創建并打開一個有名信號量
    sem_open()
    功能: initialize and open a named semaphore -> 初始化并且打開一個有名信號量
    使用格式:
    在這里插入圖片描述

    name: 有名信號量的名字,要求是必須以“/”開頭 例如: /sem_test
    oflag: O_CREAT 不存在則創建 需要額外填寫兩個參數
    O_EXCL 存在則報錯
    mode: 八進制權限 0777
    value: 有名信號量起始值

    返回值:
    成功: 有名信號量起始地址
    失敗: SEM_FAILED -1

    有名信號量P/V操作
    P操作: sem_post() 資源數+1 紅燈(0) 綠燈(1)
    V操作: sem_wait() 資源數-1 綠燈(1) 紅燈(0)
    在這里插入圖片描述
    sem: 有名信號量的地址

    關閉有名信號量
    sem_close()
    功能: sem_close - close a named semaphore
    在這里插入圖片描述

    銷毀有名信號量
    sem_unlink()
    功能: sem_unlink - remove a named semaphore
    在這里插入圖片描述

    name: 有名信號量的名字

    Jack進程與Rose進程之間使用共享內存來通信,使用有名信號量來處理同步互斥
    Jack:

    int main()
    {
    	//1. 申請key值
    	key_t key = ftok(".",10);
    	
    	//2. 根據key值申請ID號
    	int shmid = shmget(key,1024,IPC_CREAT|0666);
    	
    	//3. 根據ID號申請空間
    	char *p = (char *)shmat(shmid,NULL,0);
    	
    	//4. 創建并且打開一個有名信號量
    	sem_t *sem = NULL;
    	sem = sem_open("/sem_test",O_CREAT,0777,0);  //說明當前的資源數為0
    	
    	//5. 不斷往共享內存中寫入數據
    	while(1)
    	{
    		fgets(p,1024,stdin);  //把車開進車庫
    		
    		sem_post(sem);  //資源數為1
    		//0->1
    		
    		if(strncmp(p,"quit",4) == 0)
    		{
    			break;
    		}
    	}	
    }
    

    Rose:

    
    int main()
    {
    	//1. 申請key值
    	key_t key = ftok(".",10);
    	
    	//2. 根據key值申請ID號
    	int shmid = shmget(key,1024,IPC_CREAT|0666);
    	
    	//3. 根據ID號申請空間
    	char *p = (char *)shmat(shmid,NULL,0);
    	
    	//4. 創建并且打開一個有名信號量
    	sem_t *sem = NULL;
    	sem = sem_open("/sem_test",O_CREAT,0777,0);  //說明當前的資源數為0
    	
    	//5. 不斷往共享內存中寫入數據
    	while(1)
    	{
    		sem_wait(sem);  //一直阻塞詢問資源能否-1     如果當前資源為1,則函數返回  
    												//如果當前資源為0,則函數阻塞
    		
    		//1->0
    		printf("from Jack:%s",p);
    		
    		if(strncmp(p,"quit",4) == 0)
    		{
    			break;
    		}
    	}	
    }
    

    無名信號量
    對象: 線程
    由于無名信號量是無名的,所以說不能打開,但是可以初始化。
    sem_init()
    功能:初始化無名信號量 initialize an unnamed semaphore在這里插入圖片描述
    sem: 信號量的地址
    pshared: 作用的對象 0 線程
    非0 進程
    value:信號量的初始化值

    有名信號量P/V操作
    P操作: sem_post() 資源數+1 紅燈(0) 綠燈(1)
    V操作: sem_wait() 資源數-1 綠燈(1) 紅燈(0)

    #include <semaphore.h>
    
       int sem_post(sem_t *sem);    unlock semaphore
    
       int sem_wait(sem_t *sem);  -  lock semaphore
    
    sem: 有名信號量的地址
    

    銷毀無名信號量
    sem_destroy()
    功能: sem_destroy - destroy an unnamed semaphore

       int sem_destroy(sem_t *sem);
    
    sem:需要銷毀的無名信號量的地址
    

    創建5個線程,每一個線程的任務都是一樣
    任務: 將"helloworld"字符串1秒打印一個字符 完成任務需要10秒。
    要求5個子線程依次打印helloworld,不要同時打印。

    void *routine(void *arg)
    {
    	sem_t *sem = (sem_t *)arg; 
    	
    	//叉子:1
    	
    	//誰先能把資源數-1,誰就吃蛋糕!
    	sem_wait(sem);
    	
    	//叉子:0  -> 這時別的線程就沒辦法搶占了這個資源
    	
    	int i;
    	char buf[] = "helloworld";
    	for(i=0;buf[i]!='\0';i++)
    	{
    		fprintf(stderr,"%c",buf[i]);
    		sleep(1);
    	}
    	
    	//吃完蛋糕了,應該將叉子放出來,資源數變成1
    	sem_post(sem);
    	
    	//叉子:1  -> 別的線程就有機會搶占資源。
    	
    	pthread_exit(NULL);
    }
    
    int main()
    {
    	//1. 初始化無名信號量
    	sem_t sem;
    	sem_init(&sem,0,1); //當前資源數為0
    	
    	//2. 產生5個子線程
    	pthread_t tid[5]; //0~4
    	int i;
    	for(i=0;i<5;i++)
    	{
    		pthread_create(&tid[i],NULL,routine,(void *)&sem);
    	}
    	
    	//3. 回收資源
    	for(i=0;i<5;i++)
    	{
    		pthread_join(tid[i],NULL);
    	}
    	
    	sem_destroy(&sem);
    	
    	return 0;	
    }
    
    版權聲明:本文為JINGDIANSHUANGXI原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/JINGDIANSHUANGXI/article/details/105723438

    智能推薦

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    猜你喜歡

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    19.vue中封裝echarts組件

    19.vue中封裝echarts組件 1.效果圖 2.echarts組件 3.使用組件 按照組件格式整理好數據格式 傳入組件 home.vue 4.接口返回數據格式...

    劍指Offer39-調整數組順序使奇數位于偶數前面

    一開始想著用冒泡排序的方法來做,但是bug還是很多,后來看了評論區答案,發現直接空間換時間是最簡單的,而且和快排的寫法是類似的。...

    精品国产乱码久久久久久蜜桃不卡