线程同步——条件变量.doc_第1页
线程同步——条件变量.doc_第2页
线程同步——条件变量.doc_第3页
线程同步——条件变量.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

pthread_cond_wait()用法分析很久没看APUE,今天一位朋友问道关于一个mutex的问题,又翻到了以前讨论过的东西,为了不让自己忘记,把曾经的东西总结一下。先大体看下网上很多地方都有的关于pthread_cond_wait()的说明:条件变量 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待条件变量的条件成立而挂起;另一个线程使条件成立(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。1创建和注销条件变量和互斥锁一样,都有静态动态两种创建方式,静态方式使用PTHREAD_COND_INITIALIZER常量,如下:pthread_cond_t cond=PTHREAD_COND_INITIALIZER动态方式调用pthread_cond_init()函数,API定义如下:int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) 尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略。注销一个条件变量需要调用pthread_cond_destroy(),只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程。API定义如下:int pthread_cond_destroy(pthread_cond_t *cond)2 等待和激发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()则激活所有等待线程。现在来看一段典型的应用:看注释即可。1. #include2. #include3. 4. staticpthread_mutex_tmtx=PTHREAD_MUTEX_INITIALIZER;5. staticpthread_cond_tcond=PTHREAD_COND_INITIALIZER;6. 7. structnode8. intn_number;9. structnode*n_next;10. *head=NULL;11. 12. /*thread_func*/13. staticvoidcleanup_handler(void*arg)14. 15. printf(Cleanuphandlerofsecondthread./n);16. free(arg);17. (void)pthread_mutex_unlock(&mtx);18. 19. staticvoid*thread_func(void*arg)20. 21. structnode*p=NULL;22. 23. pthread_cleanup_push(cleanup_handler,p);24. while(1)25. pthread_mutex_lock(&mtx);/这个mutex主要是用来保证pthread_cond_wait的并发性26. while(head=NULL)/这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何这里要有一个while(head=NULL)呢?因为pthread_cond_wait里的线程可能会被意外唤醒,如果这个时候head!=NULL,则不是我们想要的情况。这个时候,应该让线程继续进入pthread_cond_wait27. pthread_cond_wait(&cond,&mtx);/pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源28. /用这个流程是比较清楚的/*block-unlock-wait()return-lock*/29. 30. p=head;31. head=head-n_next;32. printf(Got%dfromfrontofqueue/n,p-n_number);33. free(p);34. pthread_mutex_unlock(&mtx);/临界区数据操作完毕,释放互斥锁35. 36. pthread_cleanup_pop(0);37. return0;38. 39. 40. intmain(void)41. 42. pthread_ttid;43. inti;44. structnode*p;45. pthread_create(&tid,NULL,thread_func,NULL);/子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大46. /*tx6-main*/47. for(i=0;in_number=i;50. pthread_mutex_lock(&mtx);/需要操作head这个临界资源,先加锁,51. p-n_next=head;52. head=p;53. pthread_cond_signal(&cond);54. pthread_mutex_unlock(&mtx);/解锁55. sleep(1);56. 57. printf(thread1wannaendtheline.Socancelthread2./n);58. pthread_cancel(tid);/关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在最近的取消点,退出线程,而在我们的代码里,最近的取消点肯定就是pthread_cond_wait()了。关于取消点的信息,有兴趣可以google,这里不多说了59. pthread_join(tid,NULL);60. printf(Alldone-exiting/n);61. return0;62. 8楼markman1012011-12-03 08:44发表回复至于 互斥量和 条件变量一起使用的原因请看/izualzhy/archive/2011/11/14/160120.html 这句你能理解吗这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。这就是互斥量和条件一起使用的原因7楼markman1012011-12-03 08:41发表回复为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。 该怎么理解?是不是如果没有互斥量可能造成 thread_func访问临界资源时,main()也去访问造成竞争呀?6楼theboy_20002011-06-01 09:13发表回复觉得楼主的代码有问题, 61和62行应该换过来,先解锁,然后再signal, 否则34行可能会释放一个已被释放的锁了, 这个行为导致的结果可以参看UNIX环境高级编程上面写的很清楚Re:haskell2011-07-25 13:18发表回复回复theboy_2000:mutex和cond没啥必然关系,mutex同步wait和signal后相关的资源,如果没有需要同步的资源,signal不需要mutex锁住。Re:laozhuteacher2011-06-23 18:12发表回复回复 theboy_2000:哎,我也看过UNIX环境高级编程,作者的原话明明不是你的意思,作者的原话是“向等待队列发送信号时并不需要占用互斥锁”,不是说不能占用,pthread_cond_wait在返回之前会先试着锁定pthread_mutex_lock(&mtx);楼上曲解了Re:wodexinmingzi2011-12-22 09:33发表回复回复laozhuteacher:哈哈,差点我也误解了,楼主威武5楼yinluoy2011-04-21 08:41发表回复如果Linux时间被人突然修改怎么

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论