Linux IO conditional variable and semaphore

1. 将一个文件中的数据打印到终端上,类似cat一个文件。要求如下

A线程读取文件中的数据

B线程将A线程读取到的数据打印到终端上

文件打印完毕后,结束进程。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>

//创建信号量
sem_t sem;
sem_t sem1;

int flags = 0;
int fd;
char buf[1024] = {0};
ssize_t ret = 0;
//读取数据
void *callback(void *arg)
{
    int i =0;
    while (i<1000)
    {
        
        /************临界区*************/
        //P操作
        if (sem_wait(&sem) < 0)
        {
            perror("sem_wait");
            break;
        }

        ret = read(fd,buf,sizeof(buf));
        sleep(1);
        while (ret <=0)
        {
            exit(0);
        }
        

        //V操作
        if (sem_post(&sem1) < 0)
        {
            perror("sem_post");
            break;
        }
        
        /************临界区*************/
       
        
        //i++;
    }
    pthread_exit(NULL);
}

//打印数据
void *callback1(void *arg)
{
    
    int i = 0;
    while (i<1000)
    {
        /************临界区*************/
        //P操作
        if (sem_wait(&sem1) < 0)
        {
            perror("sem_wait");
            break;
        }
        write(1,buf,ret);
        //V操作
        if (sem_post(&sem) < 0)
        {
            perror("sem_post");
            break;
        }
        /************临界区*************/
    }
    pthread_exit(NULL);

}

int main(int argc, char const *argv[])
{

    //
    fd = open("01_condition_variable.c",O_RDONLY);
    if(fd < 0)
    {
        perror("open");
        return -1;
    }

   //创建信号量
   if(sem_init(&sem,0,1) < 0)
   {
     perror("sem_init");
     return -1;
   }
   if(sem_init(&sem1,0,0) < 0)
   {
     perror("sem_init");
     return -1;
   }
    //创建两个线程,一个用于打印,一个用于倒置
    pthread_t tid,tid1;
    if (pthread_create(&tid,NULL,callback,NULL) < 0)
    {
        fprintf(stderr,"pthread_create failed\n");
        return -1;
    }

    pthread_detach(tid); //tid设置分离态,pthread_join不阻塞

    if (pthread_create(&tid1,NULL,callback1,NULL) < 0)
    {
        fprintf(stderr,"pthread_create failed\n");
        return -1;
    }

    pthread_join(tid1,NULL);

    //销毁放在join之后
    if (sem_destroy(&sem) < 0)
    {
        perror("sem_destroy");
        return -1;
    }
    if (sem_destroy(&sem1) < 0)
    {
        perror("sem_destroy");
        return -1;
    }
    return 0;
}

2. 用条件变量实现,有编号为ABC的三个线程,线程内分别打印自己的线程编号,要求打印的顺序为ABC。(多个条件变量)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
#include <string.h>

//业务场景: 先打印再翻转,即使翻转抢到互斥锁也要让出

//互斥锁变量 (创建互斥锁 方式二)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

//条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;

//条件变量需要再加一个标志位
char flag = 'A';

//函数的调用不能放在全局
void *callback(void *arg)
{
    int i =0;
    while (i<1000)
    {
        
        /************临界区*************/
        //上锁
        pthread_mutex_lock(&mutex);

        //如果不是当前线程要访问的时机,则需要让当前线程休眠
        if (flag!='A')
        {
            //1.解开互斥锁,阻塞当前线程,让当前线程进入休眠阶段,等待被唤醒
            pthread_cond_wait(&cond,&mutex);
            //2. 唤醒成功后,当cpu再次调度到该线程,会尝试立即上锁
            //3.如果上锁成功,则从当前位置继续往后执行
            //4.如果上锁失败,则在当前函数位置,重新回到cond上继续休眠,等待下一次唤醒
        }
        printf("A\n");

        flag = 'B';

        //唤醒:唤醒睡在指定条件变量上的线程
        pthread_cond_signal(&cond1);

        //解锁
        pthread_mutex_unlock(&mutex);
        /************临界区*************/
       
        
        //i++;
    }
    pthread_exit(NULL);
}

void *callback1(void *arg)
{
    
    int i = 0;
    while (i<1000)
    {
        
       
        /************临界区*************/
        //上锁
        pthread_mutex_lock(&mutex);

        //如果不是当前线程要访问的时机,则需要让当前线程休眠
        if (flag!='B')   //1==>倒置 
        {
            //休眠
            //1.解开互斥锁,阻塞当前线程,让当前线程进入休眠阶段,等待被唤醒
            pthread_cond_wait(&cond1,&mutex);
            //2.唤醒成功后,当CPU再次调度到该线程,会尝试立刻上锁
            //3.如果上锁成功,则从当前位置继续往后执行
            //4.如果上锁失败,则在当前函数位置,重新回到cond上继续休眠,等待下一次唤醒
        }

        printf("B\n");

         flag = 'C';

        //唤醒:唤醒睡在指定条件变量上的线程
        pthread_cond_signal(&cond2);

        //解锁
        pthread_mutex_unlock(&mutex);
        /************临界区*************/
    }
    pthread_exit(NULL);

}


void *callback2(void *arg)
{
    
    int i = 0;
    while (i<1000)
    {
        /************临界区*************/
        //上锁
        pthread_mutex_lock(&mutex);

        //如果不是当前线程要访问的时机,则需要让当前线程休眠
        if (flag!='C')     //1==>倒置 
        {
            //休眠
            //1.解开互斥锁,阻塞当前线程,让当前线程进入休眠阶段,等待被唤醒
            pthread_cond_wait(&cond2,&mutex);
            //2.唤醒成功后,当CPU再次调度到该线程,会尝试立刻上锁
            //3.如果上锁成功,则从当前位置继续往后执行
            //4.如果上锁失败,则在当前函数位置,重新回到cond上继续休眠,等待下一次唤醒
        }
        //putchar(10);    //'\n'

        printf("C\n");

        flag = 'A';

        //唤醒:唤醒睡在指定条件变量上的线程
        pthread_cond_signal(&cond);

        //解锁
        pthread_mutex_unlock(&mutex);
        /************临界区*************/
        
        //sleep(1);
        //i++;
    }
    pthread_exit(NULL);

}

int main(int argc, char const *argv[])
{
    //创建条件变量,方式2
    /*
    if(pthread_cond_init(&cond,NULL)!=0)
    {
        fprintf(stderr,"pthread_cond_init failed __%d__\n",__LINE__);
    }
    */
    //创建两个线程,一个用于打印,一个用于倒置
    pthread_t tid,tid1,tid2;
    if (pthread_create(&tid,NULL,callback,NULL) < 0)
    {
        fprintf(stderr,"pthread_create failed\n");
        return -1;
    }

    if (pthread_create(&tid1,NULL,callback1,NULL) < 0)
    {
        fprintf(stderr,"pthread_create failed\n");
        return -1;
    }
    pthread_detach(tid); //tid设置分离态,pthread_join不阻塞
    pthread_detach(tid1);

    if (pthread_create(&tid2,NULL,callback2,NULL) < 0)
    {
        fprintf(stderr,"pthread_create failed\n");
        return -1;
    }

    pthread_join(tid2,NULL);

    //销毁放在join之后
    //销毁互斥锁
    pthread_mutex_destroy(&mutex);
    //销毁条件变量
    pthread_cond_destroy(&cond);
    pthread_cond_destroy(&cond1);
    pthread_cond_destroy(&cond2);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值