1.P、V操作原語
?P操作:
?proceduce P(var s:semaphore)
{
? begin
????? s:=s-1;
????? if(s<0)then W(s);
? end
}
V操作:
?proceduce V(var s:semaphore)
{
? begin
????? s:=s+1;
????? if(s<=0)then R(s);
? end
}
2.基本操作
數據類型:信號量的數據類型為結構sem_t,它本質上是一個長整型的數。
函數:
(1)sem_init
功能:???????? 用于創建一個信號量,并初始化信號量的值。
頭文件:?????? <semaphore.h>
函數原型:???? int sem_init (sem_t* sem, int pshared, unsigned int value);
函數傳入值:?? sem:信號量。
?????????????????? pshared:決定信號量能否在幾個進程間共享。由于目前LINUX還沒有實現進
?????????????????????????????? 程間共享信息量,所以這個值只能取0。
?????????????????? value:初始計算器
函數返回值:?? 0:成功。
?????????????????? -1:失敗。
(2)其他函數。
//等待信號量
int sem_wait?????? (sem_t* sem);
int sem_trywait?? (sem_t* sem);
//發送信號量
int sem_post?????? (sem_t* sem);
//得到信號量值
int sem_getvalue (sem_t* sem);
//刪除信號量
int sem_destroy?? (sem_t* sem);
功能:sem_wait和sem_trywait相當于P操作,它們都能將信號量的值減一,兩者的區別在
??????? 于若信號量的值小于零時,sem_wait將會阻塞進程,而sem_trywait則會立即返回。
??????? sem_post相當于V操作,它將信號量的值加一,同時發出喚醒的信號給等待的進程
?????? (或線程)。
??????? sem_getvalue 得到信號量的值。
??????? sem_destroy 摧毀信號量。
函數傳入值: sem:信號量。
函數返回值: 同上。
好了,了解完基本操作,繼續做一個練習:
這里用信號量實現互斥資源訪問的功能:
?
/*sem.c*/?
#include <stdlib.h>????
#include <stdio.h>????
#include <pthread.h>????
#include <semaphore.h>??
#include <errno.h>?????
?
/*全局變量*/?
int gnum = 0;??
/*信號量*/?
sem_t sem;??
/*聲明線程運行服務程序*/?
static void pthread_func_1 (void);?????
static void pthread_func_2 (void);?????
????
int main (void)?????
{?????
?/*線程的標識符*/?
? pthread_t pt_1 = 0;?????
? pthread_t pt_2 = 0;?????
? int ret = 0;?????
?
? /*信號量初始化*/?
? sem_init(&sem,0,1);??
? /*分別創建線程1、2*/?
? ret = pthread_create (&pt_1,????????? //線程標識符指針??
???????????????????????? NULL,????????? //默認屬性??
??????????????????????? (void *)pthread_func_1,//運行函數??
??????????????????????? NULL);????????? //無參數??
? if (ret != 0)?????
? {?????
???? perror ("pthread_1_create");?????
? }?????
????
? ret = pthread_create (&pt_2,????????? //線程標識符指針??
??????????????????????? NULL,?????????? //默認屬性????
??????????????????????? (void *)pthread_func_2, //運行函數??
??????????????????????? NULL);????????? //無參數??
? if (ret != 0)?????
? {?????
???? perror ("pthread_2_create");?????
? }?????
? /*等待線程1、2的結束*/?
? pthread_join (pt_1, NULL);?????
? pthread_join (pt_2, NULL);?????
????
? printf ("main programme exit!/n");????
? return 0;?????
}?????
?
/*線程1的服務程序*/?
static void pthread_func_1 (void)?????
{?????
? int i = 0;?????
???????
? for (;;)?????
? {?????
??? printf ("This is pthread1!/n");??????
??? sem_wait(&sem);???? /*等待信號量*/?????
??? sleep (1);???
??? /*臨界資源*/?
??? gnum++;??
??? printf ("Thread1 add one to num:%d/n",gnum);??
??????
??? sem_post (&sem);??????? /*釋放信號量*/?
?
?
???????
? }?????
}?????
/*線程2的服務程序*/???
static void pthread_func_2 (void)?????
{?????
? int i = 0;?????
????
? for (;;)?????
? {?????
??? printf ("This is pthread2!/n");???
??? sem_wait(&sem);???? /*等待信號量*/?
??? sleep (1);??
??? /*臨界資源*/?
??? gnum++;??
??? printf ("Thread2 add one to num:%d/n",gnum);??
??????
??? sem_post (&sem);??????? /*釋放信號量*/?
????
? }?????
????
? pthread_exit (0);?????
}
編譯,運行,可以看出和上次互斥鎖結果一樣的