线程同步问题实例

1.有一个队列,线程1负责从网络接收分组,并将收到的分组放到队列尾,然后再次从网络中接收下一个到达的分组,并进行同样的队列操作。线程2从此队列头中取出一个分组进行处理,处理完毕后,再次从队列中取出一个分组进行处理,处理完毕后再次从队列头取出下一个分组进行处理,两个线程都以无限循环的方式工作,因此该队列为临时资源,若队列不为空,线程2才应该开始循环处理,否则需要等待,显然如果线程2不停的检测队列是否为空,虽然能够正常工作,但是很消耗cpu资源,cpu效率低,当队列为空时,线程2进入休眠状态,当队列不为空时,线程2自动被唤醒,可以利用条件变量解决这个问题。


函数说明:

  1. #include <pthread.h> 
  2. int  pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 
#include <pthread.h>
int  pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

返回值:0代表成功,错误号代表失败

参数mutex对条件句进行保护,线程2自动把加锁的互斥量传给此函数,函数把线程2放到等待条件的线程列表上,然后对互斥量进行自动解锁,这两步操作属于原子操作,这样就不会造成条件检查和线程进入休眠状态等待之间有其它线程进入的问题,当线程2因条件不满足而进入休眠后,因为互斥量已经被解锁,于是线程1就可以加锁互斥量并将收到的分组放到队列尾,然后主动解锁互斥量,接着线程1再调用下面的pthread_cond_signal函数通知线程2条件已经发生变化。

  1. #include <pthread.h> 
  2. int  pthread_cond_signal(pthread_cond_t *cond); 
#include <pthread.h>
int  pthread_cond_signal(pthread_cond_t *cond);


返回值:0代表成功,错误号代表失败。

由于此条件发生了改变,则pthread_cond_wait函数返回,保护条件的互斥量将再次被自动加锁(注意这里是自动加锁,不需要线程2主动加锁),线程2被唤醒,于是就可以对临界资源进行操作,即线程2从队列中取出下一个分组并主动对互斥量进行解锁,之后再对该分组进行后续的处理。

  1. #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #include <sys/types.h>

    #include <unistd.h>

    #include <pthread.h>

    #include <queue>

    #include <time.h>

    std::queue<int>q;


    //静态初始化互斥量

    pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

    //静态初始化条件变量

    pthread_cond_t condition=PTHREAD_COND_INITIALIZER;

    void print(int val)

    {

        printf("获取一个新数据:%d\n",val);

    }


    void *thread1(void *arg)

    {

        srand(time(NULL));

        while (1)

        {

            pthread_mutex_lock(&mutex);//加锁互斥量

            q.push(rand()%100+1);      //向队列中插入数据

            printf("插入一个新数据\n");

            pthread_mutex_unlock(&mutex);//解锁互斥量

           //通知线程2条件发生改变

            pthread_cond_signal(&condition);

            sleep(1);

        }

    }

    void *thread2(void *arg)

    {

        srand(time(NULL));

        while (1)

        {

            pthread_mutex_lock(&mutex);//加锁互斥量

           //若队列为空,则休眠等待条件改变

            while (q.empty())

                pthread_cond_wait(&condition, &mutex);

           

           //若队列不为空,则从队列中取出一个数据

            int val=q.front();

            q.pop();

            pthread_mutex_unlock(&mutex);//解锁互斥量

            //处理数据

            print(val);

            sleep(1);

           

        }

    }


    int main()

    {

        pthread_t pit1; //线程1标志符

        pthread_t pit2; //线程2标识符

        int err=pthread_create(&pit1,NULL,thread1,NULL);//创建线程1

        if(err!=0)

        {

            perror("creat thread1 error\n");

            exit(1);

        }

        err=pthread_create(&pit2, NULL, thread2, NULL);  //创建线程2

        if(err!=0)

        {

            perror("creat thread2 error\n");

            exit(1);

        }

        while (1)

        {}

        return 0;

    }



 

2.用两个线程实现如下功能:主线程负责读取数据,当遇到特殊字符"end"后退出程序,另一个线程负责处理这些输入的数据(输出其字符串长度)。

  1. #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #include <sys/types.h>

    #include <unistd.h>

    #include <pthread.h>

    #include <time.h>

    #include <semaphore.h>

    #define WORK_SIZE 1024 //缓冲区大小

    pthread_mutex_t work_mutex;  //互斥量

    int time_to_exit=0;   //退出标记变量

    char work_area[WORK_SIZE]; //缓冲区

    void *thread_function(void *arg)//线程功能函数

    {

        sleep(1);

        pthread_mutex_lock(&work_mutex);//加锁,保证每次输入后都能进入该线程处理

        while (strncmp("end",work_area,3)!=0)//判断是否结束

        {

            printf("You input %d characters\n",strlen(work_area)-1);//输出字符串长度

            work_area[0]='\0';//相当于清空缓冲区

            pthread_mutex_unlock(&work_mutex);//解锁互斥量

            sleep(1);

           

           //判断是否在主线程执行前又再次执行该线程

            pthread_mutex_lock(&work_mutex);

            while (work_area[0]=='\0')

            {

                pthread_mutex_unlock(&work_mutex);

                sleep(1);

                pthread_mutex_lock(&work_mutex);

             }

        }

        time_to_exit=1;//更新退出标记

        work_area[0]='\0';

        pthread_mutex_unlock(&work_mutex);

        pthread_exit(0);//线程退出

    }


    int main()

    {

      

        int res;

        pthread_t a_thread;   //线程标志符

        void *thread_result;

        res=pthread_mutex_init(&work_mutex,NULL);//初始化互斥量

        if(res!=0)

        {

            perror("Mutex initialization failed");

            exit(EXIT_FAILURE);

        }

        res=pthread_create(&a_thread, NULL,thread_function, NULL);

        if (res!=0)

        {

            perror("Thread creation failed");

            exit(EXIT_FAILURE);

        }

       

        pthread_mutex_lock(&work_mutex);//加锁保证输出和输入的原子性

        printf("Input some text,Enter 'end'to finish\n");

        while (!time_to_exit)

        {

            fgets(work_area,WORK_SIZE,stdin);

           //输入成功后即可解锁

            pthread_mutex_unlock(&work_mutex);

           

           //避免在功能线程未执行前再次调用主线程,这里需要进行处理

            while (1)

            {

                pthread_mutex_lock(&work_mutex);

                if(work_area[0]!='\0')//功能线程函数还没有处理完毕

                {

                    pthread_mutex_unlock(&work_mutex);

                    sleep(1);

                }

                else

                    break //处理完毕退出

            }

        }

        pthread_mutex_unlock(&work_mutex);

       

        printf("Waiting for thread to finish...\n");

        res=pthread_join(a_thread, &thread_result);//等待功能线程退出

        if(res!=0)

        {

            printf("Thread join failed\n");

            exit(EXIT_FAILURE);

        }

        printf("Thread joined\n");

        pthread_mutex_destroy(&work_mutex);//销毁互斥量

        return 0;

    }


 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值