Linux 多任務編程——線程同步與互斥:POSIX 無名信號量

信號量概述
信號量廣泛用於進程或線程間的同步和互斥,信號量本質上是一個非負的整數計數器,它被用來控制對公共資源的訪問。

在 POSIX 標準中,信號量分兩種,一種是無名信號量,一種是有名信號量。無名信號量一般用於線程間同步或互斥,而有名信號量一般用於進程間同步或互斥。它們的區別和管道及命名管道的區別類似,無名信號量則直接保存在內存中,而有名信號量要求創建一個文件。

編程時可根據操作信號量值的結果判斷是否對公共資源具有訪問的權限,當信號量值大於 0 時,則可以訪問,否則將阻塞。PV 原語是對信號量的操作,一次 P 操作使信號量減1,一次 V 操作使信號量加1。

信號量主要用於進程或線程間的同步和互斥這兩種典型情況:

信號量用於互斥:

 

信號量用於同步:

 

無名信號量基本操作
以下函數所需頭文件:

#include <semaphore.h>

注意:編譯信號量操作函數時,需要加上參數-lpthread。

信號量數據類型爲:sem_t。

 

1)初始化信號量

int sem_init(sem_t *sem, int pshared, unsigned int value);

功能:

創建一個信號量並初始化它的值。一個無名信號量在被使用前必須先初始化。

參數:

sem:信號量的地址。

pshared:等於 0,信號量在線程間共享(常用);不等於0,信號量在進程間共享。

value:信號量的初始值。

返回值:

成功:0

失敗:-1

 

2)信號量 P 操作(減 1)

int sem_wait(sem_t *sem);

功能:

將信號量的值減 1。操作前,先檢查信號量(sem)的值是否爲 0,若信號量爲 0,此函數會阻塞直到信號量大於 0 時才進行減 1 操作。

參數:

sem:信號量的地址。

返回值:

成功:0

失敗:-1

int sem_trywait(sem_t *sem);

以非阻塞的方式來對信號量進行減 1 操作。若操作前,信號量的值等於 0,則對信號量的操作失敗,函數立即返回。

 

3)信號量 V 操作(加 1)

int sem_post(sem_t *sem);

功能:

將信號量的值加 1 併發出信號喚醒等待線程(sem_wait())。

參數:

sem:信號量的地址。

返回值:

成功:0

失敗:-1

 

4)獲取信號量的值

int sem_getvalue(sem_t *sem, int *sval);

功能:

獲取 sem 標識的信號量的值,保存在 sval 中。

參數:

sem:信號量地址。
sval:保存信號量值的地址。

返回值:

成功:0

失敗:-1

 

5)銷燬信號量

int sem_destroy(sem_t *sem);

功能:

刪除 sem 標識的信號量。

參數:

sem:信號量地址。

返回值:

成功:0

失敗:-1

 

無名信號量應用實例


信號量用於互斥實例

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
 
sem_t sem; //信號量
 
void printer(char *str)
{
    sem_wait(&sem);//減一
    while(*str)
    {
        putchar(*str);    
        fflush(stdout);
        str++;
        sleep(1);
    }
    printf("\n");
    
    sem_post(&sem);//加一
}
 
void *thread_fun1(void *arg)
{
    char *str1 = "hello";
    printer(str1);
}
 
void *thread_fun2(void *arg)
{
    char *str2 = "world";
    printer(str2);
}
 
int main(void)
{
    pthread_t tid1, tid2;
    
    sem_init(&sem, 0, 1); //初始化信號量,初始值爲 1
    
    //創建 2 個線程
    pthread_create(&tid1, NULL, thread_fun1, NULL);
    pthread_create(&tid2, NULL, thread_fun2, NULL);
    
    //等待線程結束,回收其資源
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL); 
    
    sem_destroy(&sem); //銷燬信號量
    
    return 0;
}

運行結果如下:


信號量用於同步實例:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
 
sem_t sem_g,sem_p;   //定義兩個信號量
char ch = 'a';
 
void *pthread_g(void *arg)  //此線程改變字符ch的值
{
    while(1)
    {
        sem_wait(&sem_g);
        ch++;
        sleep(1);
        sem_post(&sem_p);
    }
}
 
void *pthread_p(void *arg)  //此線程打印ch的值
{
    while(1)
    {
        sem_wait(&sem_p);
        printf("%c",ch);
        fflush(stdout);
        sem_post(&sem_g);
    }
}
 
int main(int argc, char *argv[])
{
    pthread_t tid1,tid2;
    sem_init(&sem_g, 0, 0);   //初始化信號量
    sem_init(&sem_p, 0, 1);
    
    pthread_create(&tid1, NULL, pthread_g, NULL);
    pthread_create(&tid2, NULL, pthread_p, NULL);
    
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    
    return 0;
}

運行結果如下:

 

--------------------- 
作者:Mike__Jiang 
來源:CSDN 
原文:https://blog.csdn.net/tennysonsky/article/details/46496201 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章