条件变量是利用线程间共享的全局变量进行同步的一种机制,

主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;

另一个线程使"条件成立"(给出条件成立信号)。

为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
等待条件有两种方式:条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),
其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待,
其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()
(或pthread_cond_timedwait(),下同)的竞争条件(Race Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)
或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),
而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,
mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。
激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;
而pthread_cond_broadcast()则激活所有等待线程。
 
现在来看一段典型的应用:看注释即可
 #include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h> static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; struct node
{
int n_number;
struct node*n_next;
}*head = NULL;/*[thread_func]*/ /*释放节点内存*/
static void cleanup_handler(void*arg)
{
printf("Cleanup handler of second thread.\n"); struct node *p = *((struct node**)arg);
while(p)
{
struct node* tmp = p->n_next;
free(p);
printf("free %p\n", p);
p = tmp;
} *((struct node **)arg) = NULL; (void)pthread_mutex_unlock(&mtx);
} static void* thread_func(void*arg)
{
struct node* p = NULL;
pthread_cleanup_push(cleanup_handler, &head); while()
{
pthread_mutex_lock(&mtx);
//这个mutex_lock主要是用来保护wait等待临界时期的情况,
//当在wait为放入队列时,这时,已经存在Head条件等待激活
//的条件,此时可能会漏掉这种处理
//这个while要特别说明一下,单个pthread_cond_wait功能很完善,
//为何这里要有一个while(head==NULL)呢?因为pthread_cond_wait
//里的线程可能会被意外唤醒,如果这个时候head!=NULL,
//则不是我们想要的情况。这个时候,
//应该让线程继续进入pthread_cond_wait while()
{
while(head==NULL)
{
pthread_cond_wait(&cond,&mtx);
}
//pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,
//然后阻塞在等待队列里休眠,直到再次被唤醒
//(大多数情况下是等待的条件成立而被唤醒,唤醒后,
//该进程会先锁定先pthread_mutex_lock(&mtx);,
//再读取资源用这个流程是比较清楚的
/*block-->unlock-->wait()return-->lock*/ p = head;
head = head->n_next;
printf("Got %d from front of queue\n",p->n_number);
free(p);
}
pthread_mutex_unlock(&mtx);//临界区数据操作完毕,释放互斥锁 } pthread_cleanup_pop(); return ;
} int main(void)
{
pthread_t tid;
int i;
struct node* p;
pthread_create(&tid,NULL,thread_func,NULL);
//子线程会一直等待资源,类似生产者和消费者,
//但是这里的消费者可以是多个消费者,
//而不仅仅支持普通的单个消费者,这个模型虽然简单,
//但是很强大
for(i=;i<;i++)
{
p=(struct node*)malloc(sizeof(struct node));
p->n_number=i;
pthread_mutex_lock(&mtx);//需要操作head这个临界资源,先加锁,
p->n_next=head;
head=p;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);//解锁
sleep();
} p=(struct node*)malloc(sizeof(struct node));
p->n_number=i;
pthread_mutex_lock(&mtx);//需要操作head这个临界资源,先加锁,
p->n_next=head;
head=p;
pthread_mutex_unlock(&mtx);//解锁 printf("thread1 wanna end the cancel thread2.\n");
pthread_cancel(tid);
//关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,
//子线程会在最近的取消点,退出线程,而在我们的代码里,最近的
//取消点肯定就是pthread_cond_wait()了。
pthread_join(tid,NULL); printf("All done--exiting\n"); return ;
}

phread_con_wait和pthread_mutex_lock实现的生产者消费者模型的更多相关文章

  1. Linux同步互斥(Peterson算法,生产者消费者模型)

    同步 两个或两个以上随时间变化的量在变化过程中保持一定的相对关系. 互斥 对一组并发进程,一次只有一个进程能够访问一个给定的资源或执行一个给定的功能. 互斥技术可以用于解决诸如资源争用之类的冲突,还可 ...

  2. 【Windows】用信号量实现生产者-消费者模型

    线程并发的生产者-消费者模型: 1.两个进程对同一个内存资源进行操作,一个是生产者,一个是消费者. 2.生产者往共享内存资源填充数据,如果区域满,则等待消费者消费数据. 3.消费者从共享内存资源取数据 ...

  3. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  4. Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)

    生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...

  5. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

  6. Java多线程14:生产者/消费者模型

    什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: ...

  7. Java生产者消费者模型

    在Java中线程同步的经典案例,不同线程对同一个对象同时进行多线程操作,为了保持线程安全,数据结果要是我们期望的结果. 生产者-消费者模型可以很好的解释这个现象:对于公共数据data,初始值为0,多个 ...

  8. python_way ,day11 线程,怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)

    python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...

  9. 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...

随机推荐

  1. java James

    使用JavaMail发送电子邮件(案例) 需求: 使用JavaMail技术,实现从A账户给B账户发送一封电子邮件,标题为"会议通知",邮件内容为"XX你好!请于明天下午1 ...

  2. c++ 流基本概念

    前言 在程序经常实现数据的输入和输出,c++通过一种称为流(stream)的机制提供了更为精良的输入和输出方法.流是一种灵活且面向对象的I/o方法. 根据操作对象不同分为文件流.字符串流.控制台流. ...

  3. c# 发送邮件、附件 分类: C# 2014-12-17 16:41 201人阅读 评论(0) 收藏

    WinForm窗体代码如下: <span style="font-size:14px;">using System; using System.Collections. ...

  4. win10安装MySQL

    mysql的直接地址,可以复制地址使用下载工具下载:32位:http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.26-win32.zip64位:htt ...

  5. Qt 学习之路:模型-视图高级技术

    PathView PathView是 QtQuick 中最强大的视图,同时也是最复杂的.PathView允许创建一种更灵活的视图.在这种视图中,数据项并不是方方正正,而是可以沿着任意路径布局.沿着同一 ...

  6. laravel扩展包开发步骤总结

    1. 创建包 php artisan workbench vendor/package --resources     注:  vendor:开发商名   package:包名   2.修改下包里co ...

  7. LiLei&HanMeiMei的隐式马尔可夫爱情

    一篇非常棒的隐马尔可夫入门文章...推荐! from: http://staffwww.dcs.shef.ac.uk/people/W.Liu/hmm.html

  8. java中的类集框架

    1.什么是类集框架 1.是一组类和接口 2.位于java.util包当中 3.主要用于用户存储和管理对象 4.主要分为三大类——集合.列表和映射 2.类集框架图 虚线框的表示接口,实线框的表示实现类 ...

  9. 在DataTable中更新、删除数据

    /*在DataTable中选择记录*/            /* 向DataTable中插入记录如上,更新和删除如下:             * ----但是在更新和删除前,首先要找出要更新和删除 ...

  10. SQL语句之二建表

    use Test --进入需要建表的数据库if exists(select * from sysobjects where name='MyTable')--表是否已经存在drop table MyT ...