Linux-线程同步信号量
信号量用于多线程多任务同步,一个线程完成了某一个动作后就通过信号量告诉其他线程再进行某些动作,其他线程在等待某一个线程时会阻塞。
init
sem_t sem;
sem_init(&sem,0,0); 函数原型如下:
int sem_init(sem_t *sem, int pshared, unsigned int value);
pshared:0:shared between the threads of process.
!0:shared between processes.
value: initial value for the semaphore.
wait
sem_wait(&sem);
P操作,if(value>0);value--;执行代码。if(value<=0);阻塞并等待post把value+1。
post
sem_post(&sem);
V操作,value++;通知wait进行value的原子操作,V操作不阻塞继续执行。
trywait
sem_trywait(&sem);
非阻塞版,如果信号量计数大于0,则信号量立即减1并返回0,否则立即返回-1。
getvalue
sem_getvalue(&sem, &sval)
读取sem中信号量计数,存于sval中,并返回0。
/*gcc sem.c -lpthread*/
//用户从终端输入任意字符然后统计个数显示,输入end则结束
//使用多线程实现:主线程获取用户输入并判断是否退出,子线程计数
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
char buf[100]={0};
int flag = 0;
sem_t sem;
// 子线程程序,作用是统计buf中的字符个数并打印
void *func(void*arg)
{
// 子线程首先应该有个循环
// 循环中阻塞在等待主线程激活的时候,子线程被激活后就去获取buf中的字符
// 长度,然后打印;完成后再次被阻塞
sem_wait(&sem);
while(flag==0)
{
printf("长度为:%ld.\n",strlen(buf));
memset(buf, 0, sizeof(buf));
sem_wait(&sem);
}
pthread_exit(NULL);
}
int main(void)
{
int ret=-1;
pthread_t th;
sem_init(&sem,0,0);
ret=pthread_create(&th,NULL,func,NULL);
if (ret != 0)
{
printf("pthread_create error.\n");
return -1;
}
printf("输入一个字符串,以回车结束.\n");
while(scanf("%s",buf))
{
// 去比较用户输入的是不是end,如果是则退出,如果不是则继续
if(!strncmp(buf,"end",3))
{
printf("输入的字符串为:%s\n",buf);
flag=1;
sem_post(&sem);
break;
}
// 主线程在收到用户收入的字符串,并且确认不是end后
// 就去发信号激活子线程来计数。
// 子线程被阻塞,主线程可以激活,这就是线程的同步问题。
// 信号量就可以用来实现这个线程同步
sem_post(&sem);
}
// 回收子线程
printf("等待回收子线程\n");
ret = pthread_join(th, NULL);
if (ret != 0)
{
printf("pthread_join error.\n");
exit(-1);
}
printf("子线程回收成功\n");
sem_destroy(&sem);
return 0;
}
//intsem_wait(sem_t *sem); 等待信号量,如果信号量的值大于0,将信号量的值减1,立即返回。
//如果信号量的值为0,则线程阻塞。相当于P操作。成功返回0,失败返回-1。
//intsem_post(sem_t *sem); 释放信号量,让信号量的值加1。相当于V操作。