本文的信号量类型为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
#include
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回收线程