在上一篇文章中,講述了線程中互斥鎖的使用,達到對共用資源互斥使用。除了使用互斥鎖,訊號量,也就是作業系統中所提到的PV原語,能達到互斥和同步的效果,這就是今天我們所要講述的訊號量線程式控制制。
PV原語是對整數計數器訊號量sem的操作,一次P操作可使sem減一,而一次V操作可是sem加一。進程(或線程)根據訊號量的值來判斷是否對公用資源具有存取權限。當訊號量的值大於零或等於零的時候,該進程(或線程)具有對公用資源訪問的許可權,否則,當訊號量的值小於時,該進程(或線程)就會被阻塞,直到訊號量的值大於或等於一。
1、在LINUX中,實現了POSIX的無名訊號量,主要用於線程間的互斥同步,下面將簡單介紹一些函數介面:
(1)、sem_init
功能: 用於建立一個訊號量,並初始化訊號量的值。
標頭檔: <semaphore.h>
函數原型: int sem_init (sem_t* sem, int pshared, unsigned int value);
函數傳入值: sem:訊號量。
pshared:決定訊號量能否在幾個進程間共用。由於目前LINUX還沒有實現進
程間共用資訊量,所以這個值只能取0。
函數傳回值: 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:訊號量。
函數傳回值: 同上。
2、函數實現。
#include <stdio.h><br />#include <stdlib.h><br />#include <unistd.h><br />#include <pthread.h><br />#include <semaphore.h><br />#include <errno.h> </p><p>#define return_if_fail(p) /<br />if((p) == 0){printf ("[%s]: func error!", __func__);return;} </p><p>typedef struct _PrivInfo<br />{<br /> sem_t sem;<br /> int lock_var;<br /> time_t end_time;<br />}PrivInfo; </p><p>static void info_init (PrivInfo* thiz);<br />static void* pthread_func_1 (PrivInfo* thiz);<br />static void* pthread_func_2 (PrivInfo* thiz); </p><p>int main (int argc, char** argv)<br />{<br /> pthread_t pt_1 = 0;<br /> pthread_t pt_2 = 0;<br /> int ret = 0;<br /> PrivInfo* thiz = NULL; </p><p> thiz = (PrivInfo* )malloc (sizeof (PrivInfo));<br /> if (thiz == NULL)<br /> {<br /> printf ("[%s]:Failed to malloc PrivInfo./n");<br /> return -1;<br /> } </p><p> info_init (thiz); </p><p> ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);<br /> if (ret != 0)<br /> {<br /> perror ("pthread_1_create:");<br /> } </p><p> ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);<br /> if (ret != 0)<br /> {<br /> perror ("pthread_2_create:");<br /> } </p><p> pthread_join (pt_1, NULL);<br /> pthread_join (pt_2, NULL); </p><p> sem_destroy (&thiz->sem);<br /> free (thiz);<br /> thiz = NULL; </p><p> return;<br />} </p><p>static void info_init (PrivInfo* thiz)<br />{<br /> return_if_fail (thiz != NULL); </p><p> thiz->lock_var = 0;<br /> thiz->end_time = time(NULL) + 10; </p><p> sem_init (&thiz->sem, 0, 1); </p><p> return;<br />} </p><p>static void* pthread_func_1 (PrivInfo* thiz)<br />{<br /> return_if_fail(thiz != NULL); </p><p> int i = 0; </p><p> while (time(NULL) < thiz->end_time)<br /> {<br /> sem_wait (&thiz->sem);<br /> printf ("pthread: pthread1 get lock./n"); </p><p> for (i = 0; i < 2; i ++)<br /> {<br /> thiz->lock_var ++;<br /> sleep (1);<br /> } </p><p> sem_post (&thiz->sem);<br /> printf ("pthread1: pthread1 unlock/n"); </p><p> sleep (1);<br /> } </p><p> return;<br />} </p><p>static void* pthread_func_2 (PrivInfo* thiz)<br />{<br /> return_if_fail (thiz != NULL); </p><p> while (time (NULL) < thiz->end_time)<br /> {<br /> sem_wait (&thiz->sem);<br /> printf ("pthread2: pthread2 get lock!/n");<br /> printf ("the lock_var = %d/n", thiz->lock_var); </p><p> sem_post (&thiz->sem);<br /> printf ("phtread2: pthread2 unlock./n"); </p><p> sleep (3);<br /> } </p><p> return;<br />}<br />
從上面的執行個體中可以看出,通過訊號量實現共用資源中的互斥使用,跟上一篇文章中的互斥鎖的效果是一樣的。但是通過互斥鎖還有一個更加方便的功能,就是同步。下一篇文章將講述線程間通過訊號量的同步實現。
~~END~~