POSIX信号量
POSIX信号量和SystemV信号量作用相同,都是用于同步操作。
信号量和互斥锁的区别:互斥锁只允许一个线程进入临界区;信号量同一时刻允许多个线程进入临界区。
(1)初始化信号量#include<semaphore.h>
int sem_init(sem_t *sem,int pshared,unsigned int value);
参数:
sem: 信号量地址;
pshared: 0表示线程间通信,非0表示进程间通信;
value: 信号量的初始值;
(2)等待信号量与发布信号量
//类似P操作
int sem_wait(sem_t *sem);//阻塞
int sem_trywait(sem_t *sem);//非阻塞
sem_wait()将信号量的值减1,操作前要检查(sem)是否为0,若为0,则线程会阻塞,直到大于0时进行减1操作;sem_trywait()以非阻塞的方式对信号量减1,如果(sem)等于0,对信号量操作失败,立即返回。
(3)发布信号量
//类似V操作
int sem_post(sem_t *sem);
释放信号量,将信号量的值加1,并发出信号唤醒等待线程(sem_wait())。
(4)获取信号量的值
int sem_getvalue(sem_t *sem,int *sval);
获取信号量sem的值,并保存在sval中。
参数:
sem:信号量地址;
sval: 保存信号量的地址
(5)销毁信号量
int sem_destroy(sem_t *sem);
例子:主线程输入字符串,子线程统计个数并打印
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>
char buf[1024] = {0};
int flag;
sem_t sem;//定义信号量
//子线程统计字符串的长度
//子线程应该有个循环
//循环中阻塞在等待主线程激活的时候,子线程激活就去统计
//统计完毕后,再次被阻塞
void* pthread_func(void* arg)
{
sem_wait(&sem);//等待信号量
while(flag==0)
{
printf("长度为:%d\n",strlen(buf));
memset(buf,0,sizeof(buf));
sem_wait(&sem);
}
return NULL;
}
int main()
{
pthread_t tid;
//初始化信号量
sem_init(&sem,0,0);
//创建线程
int ret = pthread_create(&tid,NULL,pthread_func,NULL);
if(ret<0)
{
perror("pthread_create");
return -1;
}
printf("输入一个字符串,回车结束!\n");
while(scanf("%s",buf))
{
//主线程接收用户输入的字符串,并且确认不是end
//就去发送信号激活子线程计数
//子线程阻塞,主线程可以激活
if(!strncmp(buf,"end",3))
{
printf("输入的字符串为:%s\n",buf);
flag=0;
sem_post(&sem);//发布信号量
break;
}
sem_post(&sem);
}
//回收子线程
printf("等待子线程回收!\n");
ret = pthread_join(tid,NULL);
if(ret!=0)
{
perror("pthread_join");
exit(-1);
}
printf("子线程回收成功!\n");
//销毁信号量
sem_destroy(&sem);
return 0;
}
结果: