线程同步---信号量

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;
}

结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/prefect_boy/article/details/79946489