首先要了解线程之间的信号量的系统函数
信号量的类型为sem_t
#include<semaphore.h>
int sem_init (sem_t *sem, int pshared, unsigned int value);
这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。
sem为指向信号量结构的一个指针
pshared参数控制着信号量的类型。如果 pshared的值是0,就表示它是当前进程的局部信号量;否则,其它进程就能够共享这个信号量,一般为0。
value给出了信号量的初始值
int sem_wait(sem_t * sem);
对应p操作
int sem_post(sem_t * sem);
对应v操作
关于信号量pv操作可以看信号量集知识整理
int sem_getvalue(sem_t *sem, int *valp);
获得信号量sem的值,并保存到valp中
int sem_destroy (sem_t *sem);
清理信号量的时候如果还有线程在等待它,用户就会收到一个错误。
然而在linux的线程中,其实是没有任何资源关联到信号量对象需要释放的,因此在linux中,销毁信号量对象的作用仅仅是测试是否有线程因为该信号量在等待。如果函数返回0说明没有,正常注销信号量,如果返回EBUSY,说明还有线程正在等待该信号量的信号。
信号量的使用如下步骤小结
1.声明信号量sem_t sem1;
2.初始化信号量sem_init(&sem1,0,1);
3.sem_post和sem_wait函数配合使用来达到线程同步
4.释放信号量int sem_destroy (sem_t *sem1);
下面是实现多线程之间交替打印成对字符的例子
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<semaphore.h>
sem_t resource;//定义信号量
void* f1(void* arg)
{
int i = 0;
char c = ((char*)arg)[0];
for(;i<10;i++)
{
sem_wait(&resource);//p操作
printf("%c",c);
fflush(stdout);
sleep(rand()%3);
printf("%c",c);
fflush(stdout);
sem_post(&resource);//v操作
sleep(rand() % 2);
}
}
int main()
{
pthread_t t1,t2,t3;
sem_init(&resource,0,1);//初始化信号量
pthread_create(&t1,NULL,f1,const_cast<char*>("0"));//创建3个线程,并传参要打印的字符,const_cast把const char*转换为char*
pthread_create(&t2,NULL,f1,const_cast<char*>("x"));
pthread_create(&t3,NULL,f1,const_cast<char*>("#"));
pthread_join(t1,NULL);//确保3个线程都执行完毕
pthread_join(t2,NULL);
pthread_join(t3,NULL);
sem_destroy(&resource);//销毁信号量
return 0;
}
g++ test2.cpp -g -o test2.exe -lpthread
<93 mdsp209 [mct] :/home/mdcc/mct/cpp/shm>./test2.exe
0000xx####xx00##xxxxxxxx0000xx000000xxxxxx00##00############