码迷,mamicode.com
首页 > 编程语言 > 详细

linux网络编程----->线程同步-->条件变量

时间:2016-06-17 00:53:40      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:条件变量   互斥锁   互斥量网络编程   linux   共享资源   多线程   

开发使用多线程过程中, 不可避免的会出现多个线程同时操作同一块共享资源, 当操作全部为读时, 不会出现未知结果, 一旦当某个线程操作中有写操作时, 就会出现数据不同步的事件. 

    而出现数据混乱的原因:


    • 资源共享(独享资源则不会)

    • 调试随机(对数据的访问会出现竞争)

    • 线程间缺少必要的同步机制   

    以上三点, 前两点不能被改变. 欲提高效率, 传递数据, 资源必须共享. 只要资源共享, 就一定会出现线程间资源竞争, 只要存在竞争关系, 数据就会出现混乱.

    所以只能从第三点着手, 使多个线程在访问共享资源的时候, 出现互斥.

线程同步:

    指在一定的时间里只允许某一个进程访问某个资源,而在此时间内,不允许其它线程对该资源进行操作.

    

线程的同步机制:

    • 互斥量(互斥锁)

    • 读写锁

    • 条件变量(需要配合互斥量(互斥锁)来使用)

    • 信号量        


    由于前章节介绍完了互斥量(互斥锁)和读写锁,  本次介绍条件变量


    条件变量(需要配合互斥量(互斥锁)来使用):

        条件变量本身不是锁! 但它可以造成阻塞.通常与互斥量(互斥锁)一起使用,给多线程提供一个会合的场所.给互斥量(互斥锁)一层包装.

    条件变量主要用的API:

      初始化条件变量

        pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);   

           参数1:cond 传入的一个条件变量地址

           参数2:attr 表示条件变量的属性,没有特殊需求一般填NULL

           restrice: C99标准类型限定符, 用于告诉编译器,该指向的对象已被引用,不能被除该指针外的所有直接或间接的方法修改该指向的内容.

     

     销毁一个条件变量      

        pthread_cond_destroy(pthread_cond_t* cond);    

           参数: cond 传入的一个条件变量地址

        

     阻塞等待一个条件变量

        pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);   

           参数1: cond传入一个已经初始好的条件变量地址

           参数2: mutex传入一个已经初始化好的互斥量(互斥锁)

           restrice: C99标准类型限定符, 用于告诉编译器,该指向的对象已被引用,不能被除该指针外的所有直接或间接的方法修改该指向的内容.

        函数作用:

            1.阻塞等待条件变量(参1)满足

            2.释放已掌握的护持锁(解锁互斥量)相当于pthread_mutex_unlock(&mutex);

                    1. 2两步为一个原子操作

            3.当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取护持锁;


      限时等待一个条件变量:

        pthread_cond_timewait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);

           参数1: cond传入一个已经初始好的条件变量地址

           参数2: mutex传入一个已经初始化好的互斥量(互斥锁)

           参数3: abstime传入一个绝对时间解构体, struct timespes结构体

                                        struct timespec{

                                                time_t tv_sec;        /*seconds*/ 秒

                                                long tv_nsec;        /*nanosecondes*/    纳秒


            唤醒至少一个阻塞在条件变量上的线程

                  pthread_cond_signal(pthread_cond_t* cond);

                        参数: cond传入一个已经初始好的条件变量地址


     唤醒全部阻塞在条件变量上的线程

        pthread_cond_broadcast(pthread_cond_t* cond);

            参数: cond传入一个已经初始好的条件变量地址


     案例: 

       程同步典型的案例即为生产者消费者模型,而借助条件变量来实现这一模型,是比较常见的一种方法。假定有两个线程,一个模拟生产者行为,一个模拟消费者行为。两个线程同时操作一个共享资源(一般称之为汇聚),生产向其中添加产品,消费者从中消费掉产品。

      

        看如下示例,使用条件变量模拟生产者、消费者问题:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>

//链表节点结构体
struct msg{
	struct msg* next;	//指针域
	int num;		//数据域
};

struct msg* head;	//全局头指针

pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void* consumer(void* args){
	struct msg* mp = NULL;	//创建一个节点指针
	for(;;){	//无限循环
		pthread_mutex_lock(&lock);	//加锁
		//?为何为while不为if, 
		//如果消费者或其它线程提早调用了pthread_cond_signal,而没有产生数据
		//而此时头指针还是为空, if会造成程序崩溃
		while(NULL == head){	//头指针为空,说明没有数据
			pthread_cond_wait(&has_product, &lock);
		}
		mp = head;	//获取数据节点
		head = mp->next;	//模拟消费一个产品
		pthread_mutex_unlock(&lock);

		printf("-Consume --%d\n", mp->num); //打屏提示
		free(mp);	//释放
		sleep(rand() % 5);	//等待一段时间
	}
}

void* producer(void* args){
	struct msg* mp = NULL;
	for(;;){
		//生产一个产品
		mp = (struct msg*)malloc(sizeof(struct msg));
		mp->num = rand() % 1000 + 1; //1-1000之间

		printf("-Produce ---%d\n", mp->num);

		pthread_mutex_lock(&lock);	//加锁
		mp->next = head;
		head = mp;	//头插法加入产品链表
		pthread_mutex_unlock(&lock);	//解锁
		//将等待在该条件变量的线程唤醒
		pthread_cond_signal(&has_product);
		sleep(rand()%5);	//等待
	}
}

int main(int argc, char* argv[]){
	pthread_t pid, cid;
	srand(time(NULL)); //随机数种子

	pthread_create(&pid, NULL, producer, NULL); //创建一个生产者线程
	pthread_create(&cid, NULL, consumer, NULL); //创建一个消费者线程

	pthread_join(pid, NULL);//等待消费者线程结束
	pthread_join(cid, NULL);//等待生产者线程结束
	return 0;
}

运行结果:

    技术分享

本文出自 “sea” 博客,请务必保留此出处http://lisea.blog.51cto.com/5491873/1790097

linux网络编程----->线程同步-->条件变量

标签:条件变量   互斥锁   互斥量网络编程   linux   共享资源   多线程   

原文地址:http://lisea.blog.51cto.com/5491873/1790097

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!