本文的信號量類型爲POSIX無名信號量
1、信號量基礎知識
我們通常寫程序時會定義的一個變量flag,然後用if判斷,當flag爲1時執行,flag爲0時不執行某段程序,而信號量sem就像一個flag一樣,只不過是在線程中使用,通過信號量我們可以控制多個線程的執行順序。
2、信號量的主要用到的函數
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_post(sem_t *sem);
sem_init():初始化信號量,其中sem是要初始化的信號量,信號量變量用sem_t 定義,例:sem_t A,B,C;定義信號量A,B,C,pshared表示此信號量是在進程間共享還是線程間共享,由於目前 Linux 還沒有實現進程間共享信號量,所以這個值只能夠取 0,就表示這個信號量是當前進程的局部信號量,value是信號量的初始值,也就相當於flag的初始值。成功返回0,失敗返回-1。
sem_wait()函數是等待(獲取)信號量,如果信號量的值大於0,將信號量的值減1,立即返回。如果信號量的值爲0,則進程/線程阻塞。成功返回0,失敗返回-1。
sem_trywait()函數也是等待信號量,如果指定信號量的計數器爲0,那麼直接返回EAGAIN錯誤,而不是阻塞等待。
sem_post()函數是釋放信號量,讓信號量的值加1。成功返回0,失敗返回-1。
sem_destroy():銷燬信號量,其中sem是要銷燬的信號量。只有用sem_init初始化的信號量才能用sem_destroy()函數銷燬。成功返回0,失敗返回-1。
3、使用信號量實現循環打印n個ABC
#include<bits/stdc++.h>
#include<semaphore.h>
using namespace std;
sem_t semA,semB,semC;
pthread_t pa,pb,pc;
void* printA(void* arg)
{
int n = (unsigned long long)arg;
for(int i=1;i<=n;i++)
{
sem_wait(&semA);
cout<<"A";
sem_post(&semB);
}
pthread_exit(NULL);//退出線程
}
void* printB(void* arg)
{
int n = (unsigned long long)arg;
for(int i=1;i<=n;i++)
{
sem_wait(&semB);
cout<<"B";
sem_post(&semC);
}
pthread_exit(NULL);//退出線程
}
void* printC(void* arg)
{
int n = (unsigned long long)arg;
for(int i=1;i<=n;i++)
{
sem_wait(&semC);
cout<<"C";
sem_post(&semA);
}
pthread_exit(NULL);//退出線程
}
int main()
{
int n;
while(cin>>n)
{
sem_init(&semA,0,1);
sem_init(&semB,0,0);
sem_init(&semC,0,0);
pthread_create(&pa,NULL,printA,(void*)(unsigned long long)(n));
pthread_create(&pb,NULL,printB,(void*)(unsigned long long)(n));
pthread_create(&pc,NULL,printC,(void*)(unsigned long long)(n));
void * thread_ret;
pthread_join(pa,&thread_ret);
pthread_join(pb,&thread_ret);
pthread_join(pc,&thread_ret);
sem_destroy(&semA);
sem_destroy(&semB);
sem_destroy(&semC);
}
}
代碼的運行環境是linux,在終端使用g++ name.cpp -o test -lpthread -static
使用函數pthread_create創建線程,給線程函數傳遞參數n
使用函數pthread_join回收線程