1.信號量概述
信號量是一個底層核心模塊【int】類型變量,記錄當前信號量數據。
信號量 P 操作 (sem_wait)
????????線程檢測對應信號量底層 int 數據數值,如果大于 0,當前線程獲得 CPU 執行權,同時將信號量底層 int 數據-1 操作。
如果底層數據為 0,當前線程無法獲取 CPU 執行權,進入阻塞狀態。同時等待信號量 > 0
信號量 V 操作 (sem_post)
????????線程任務執行完畢,執行 V 操作,對當信號量底層 int 數據 +1,相當于釋放 CPU 執行權。
信號量可以控制線程互斥和線程同步。
2.信號量相關API
2.1sem_init初始化
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value)
函數功能:
????????用于初始化一個信號量變量,提供必要的參數,限制當前信號量是針對于【線程操作】還是【進程操作】
函數參數:
????????sen_t *sem:
?信號量變量地址
????????int? pshared:
?控制值當前信號量,限制內容為線程還是進程,線程參數要求為 0, 不等于 0 為進程間操作。建議 0 線程, 1 進程。
????????unsigned int value:
?信號量初始化數據,通常情況下為 1?
返回值:
????????成功返回 0
????????失敗返回 -1
2.2sem_wait? ?P操作/等待操作
#include <semaphore.h>
int sem_wait(sem_t *sem)
函數功能:
????????信號量 P 操作,當前信號量-1。
????????如果為 0 當前線程/進程進入阻塞狀態。
????????如果不為 0,信號量 -= 1,同時可以執行目標線程/進程代碼。
函數參數:
????????sem_t *sem:
?信號量變量地址
返回值類型:
????????成功返回 0
????????失敗返回 -1
2.3sem_post? V操作/釋放操作
#include <semaphore.h>
int sem_post(sem_t *sem)
函數功能:
????????信號量 V 操作,當前信號量 +1
????????信號量不為 0,相當于解除與當前信號量相關的其他線程/進程阻塞狀態
函數參數:
????????sem_t *sem :
?信號量變量地址
返回值類型
????????成功返回 0
????????失敗返回 -1
2.4sem_destroy? 銷毀操作
#include <semaphore.h>
int sem_destroy(sem_t *sem)
函數功能:
????????銷毀當前信號量變量
函數參數:
????????sem_t? *sem:
?信號量變量地址
返回值類型
????????成功返回 0
????????失敗返回 -1
2.5信號量的操作案例
將上面的信號量函數進行綜合應用
2.5.1信號量互斥控制
相當于互斥鎖的作用
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
sem_t sem;
void *threadA_task(void *arg);
void *threadB_task(void *arg);
void *threadC_task(void *arg);
void print_string(const char *str);
// 線程 A 對應的線程【句柄】類型
pthread_t tid1;
// 線程 B 對應的線程【句柄】類型
pthread_t tid2;
// 線程 C 對應的線程【句柄】類型
pthread_t tid3;
int main(int argc, char const *argv[])
{int status = 0;/*1. 初始化信號量初始化當前信號量,對應的控制目標為線程,初始化數據為 1int sem_init (sem_t *__sem, int __pshared, unsigned int __value)*/status = sem_init(&sem, 0, 3);//int? pshared:?控制值當前信號量,限// 制內容為線程還是進程,線程參數要求為 0, //不等于 0 為進程間操作。建議 0 線程, 1 進程。if (status){printf("semaphore init failed!\n");_exit(1);}status = pthread_create(&tid1, NULL, threadA_task, "Hello World!");if (status){printf("pthread_create threadA failed!\n");_exit(1);}status = pthread_create(&tid2, NULL, threadB_task, "Hello HH!");if (status){printf("pthread_create threadB failed!\n");_exit(1);}status = pthread_create(&tid3, NULL, threadC_task, "Hello GL!");if (status){printf("pthread_create threadC failed!\n");_exit(1);}pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);return 0;
}
void *threadA_task(void *arg)
{// 信號量 P 操作sem_wait(&sem);print_string((const char *)arg);// 信號量 V 操作sem_post(&sem);
}
void *threadB_task(void *arg)
{// 信號量 P 操作sem_wait(&sem);print_string((const char *)arg);// 信號量 V 操作sem_post(&sem);
}
void *threadC_task(void *arg)
{// 信號量 P 操作sem_wait(&sem);print_string((const char *)arg);// 信號量 V 操作sem_post(&sem);
}
void print_string(const char *str)
{while (*str){printf("%c\n", *str);sleep(1);str += 1;}
}
2.5.1信號量執行流程控制
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
sem_t sem1;
sem_t sem2;
sem_t sem3;
void *threadA_task(void *arg);
void *threadB_task(void *arg);
void *threadC_task(void *arg);
void print_string(const char *str);
// 線程 A 對應的線程【句柄】類型
pthread_t tid1;
// 線程 B 對應的線程【句柄】類型
pthread_t tid2;
// 線程 C 對應的線程【句柄】類型
pthread_t tid3;
int main(int argc, char const *argv[])
{int status = 0;/*1. 初始化信號量初始化當前信號量,對應的控制目標為線程,初始化數據為 1int sem_init (sem_t *__sem, int __pshared, unsigned int __value)*/status = sem_init(&sem1, 0, 1);if (status){printf("semaphore init failed!\n");_exit(1);}status = sem_init(&sem2, 0, 0);if (status){printf("semaphore init failed!\n");_exit(1);}status = sem_init(&sem3, 0, 0);if (status){printf("semaphore init failed!\n");_exit(1);}status = pthread_create(&tid1, NULL, threadA_task, "Hello World!");if (status){printf("pthread_create threadA failed!\n");_exit(1);}status = pthread_create(&tid2, NULL, threadB_task, "Hello HH!");if (status){printf("pthread_create threadB failed!\n");_exit(1);}status = pthread_create(&tid3, NULL, threadC_task, "Hello GL!");if (status){printf("pthread_create threadC failed!\n");_exit(1);}pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);// 線程銷毀pthread_cancel(tid1);pthread_cancel(tid2);pthread_cancel(tid3);// 信號量銷毀sem_destroy(&sem1);sem_destroy(&sem2);sem_destroy(&sem3);return 0;
}
void *threadA_task(void *arg)
{// sem1 信號量 P 操作sem_wait(&sem1);print_string((const char *)arg);// sem2 信號量 V 操作sem_post(&sem2);
}
void *threadB_task(void *arg)
{// sem2 信號量 P 操作sem_wait(&sem2);print_string((const char *)arg);// sem3 信號量 V 操作sem_post(&sem3);
}
void *threadC_task(void *arg)
{// sem3 信號量 P 操作sem_wait(&sem3);print_string((const char *)arg);// sem1 信號量 V 操作sem_post(&sem1);
}
void print_string(const char *str)
{printf("%s\n", str);sleep(5);
}