1. 程式人生 > >多執行緒程式設計之六:pthread訊號量

多執行緒程式設計之六:pthread訊號量

###Date: 2017/11/13

轉載自:http://blog.csdn.net/lovecodeless/article/details/24919511 Pthread是 POSIX threads 的簡稱,是POSIX的執行緒標準 互斥量用來處理一個共享資源的同步訪問問題,當有多個共享資源時,就需要用到訊號量機制。 訊號量機制用於保證兩個或多個共享資源被執行緒協調地同步使用,訊號量的值對應當前可用資源的數量。          1.訊號量samaphore):         訊號量機制通過訊號量的值控制可用資源的數量。執行緒訪問共享資源前,需要申請獲取一個訊號量,如果訊號量為0,說明當前無可用的資源,執行緒無法獲取訊號量,則該執行緒會等待其他資源釋放訊號量(訊號量加1)。如果訊號量不為0,說明當前有可用的資源,此時執行緒佔用一個資源,對應訊號量減1。
        舉例:         停車場有5個停車位,汽車可使用停車位。在這裡5個停車位是共享的資源,汽車是執行緒。開始訊號量為5,表明此時有5個停車位可用。一輛汽車進入停車場前,先查詢訊號量的值,不為0表明有可用停車位,汽車進入停車場並使用一個停車位,訊號量減1,表明佔用一個停車位,可用數減少。            2.訊號量基本函式          #include <semaphore.h>
初始化訊號量:
        int sem_init(sem_t *sem, int pshared, unsigned int val);
        該函式第一個引數為訊號量指標,第二個引數為訊號量型別(一般設定為0),第三個為訊號量初始值。第二個引數pshared為0時,該程序內所有執行緒可用,不為0時不同程序間可用。

訊號量減1:
        int sem_wait(sem_t *sem);
        該函式申請一個訊號量,當前無可用訊號量則等待,有可用訊號量時佔用一個訊號量,對訊號量的值減1。
訊號量加1:
        int sem_post(sem_t *sem);
        該函式釋放一個訊號量,訊號量的值加1。
銷燬訊號量:
        int sem_destory(sem_t *sem);
        該函式銷燬訊號量。         3.牛刀小試         採用訊號量機制,解決蘋果橙子問題:一個能放N(這裡N設為3)個水果的盤子,爸爸只往盤子裡放蘋果,媽媽只放橙子,女兒只吃盤子裡的橙子,兒子只吃蘋果。
        採用三個訊號量:         1.sem_t empty:訊號量empty控制盤子可放水果數,初始為3,因為開始盤子為空可放水果數為3。         2.sem_t  apple ;訊號量apple控制兒子可吃的蘋果數,初始為0,因為開始盤子裡沒蘋果。         3.sem_t orange;訊號量orange控制女兒可吃的橙子是,初始為0,因為開始盤子裡沒橙子。 注:互斥量work_mutex只為printf輸出時能夠保持一致,可忽略。 DEMO:
#include <stdio.h>
#include <pthread.h>
#include <Windows.h>
#include <semaphore.h>
#pragma comment(lib, "pthreadVC2.lib")     //必須加上這句
sem_t empty;  //控制盤子裡可放的水果數
sem_t apple;  //控制蘋果數
sem_t orange; //控制橙子數
pthread_mutex_t work_mutex;                    //宣告互斥量work_mutex
void *procf(void *arg) //father執行緒
{
	while (1){
		sem_wait(&empty);     //佔用一個盤子空間,可放水果數減1
		pthread_mutex_lock(&work_mutex);     //加鎖
		printf("爸爸放入一個蘋果!\n");
		sem_post(&apple);     //釋放一個apple訊號了,可吃蘋果數加1
		pthread_mutex_unlock(&work_mutex);   //解鎖
		Sleep(3000);
	}

}
void *procm(void *arg)  //mother執行緒
{
	while (1){
		sem_wait(&empty);
		pthread_mutex_lock(&work_mutex);     //加鎖
		printf("媽媽放入一個橙子!\n");
		sem_post(&orange);
		pthread_mutex_unlock(&work_mutex);   //解鎖
		Sleep(4000);
	}
}
void *procs(void *arg)  //son執行緒
{
	while (1){
		sem_wait(&apple);       //佔用一個蘋果訊號量,可吃蘋果數減1 
		pthread_mutex_lock(&work_mutex);     //加鎖
		printf("兒子吃了一個蘋果!\n");
		sem_post(&empty);       //吃了一個蘋果,釋放一個盤子空間,可放水果數加1
		pthread_mutex_unlock(&work_mutex);   //解鎖
		Sleep(1000);
	}
}
void *procd(void *arg)  //daughter執行緒
{
	while (1){
		sem_wait(&orange);
		pthread_mutex_lock(&work_mutex);     //加鎖
		printf("女兒吃了一個橙子!\n");
		sem_post(&empty);
		pthread_mutex_unlock(&work_mutex);   //解鎖
		Sleep(2000);
	}

}

void main()
{
	pthread_t father;  //定義執行緒
	pthread_t mother;
	pthread_t son;
	pthread_t daughter;

	sem_init(&empty, 0, 3);  //訊號量初始化
	sem_init(&apple, 0, 0);
	sem_init(&orange, 0, 0);
	pthread_mutex_init(&work_mutex, NULL);   //初始化互斥量

	pthread_create(&father, NULL, procf, NULL);  //建立執行緒
	pthread_create(&mother, NULL, procm, NULL);
	pthread_create(&daughter, NULL, procd, NULL);
	pthread_create(&son, NULL, procs, NULL);

	Sleep(1000000000);
}

result: