免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 13703 | 回复: 8
打印 上一主题 下一主题

pthread_cond_signal()的具体位置? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-03-15 14:13 |只看该作者 |倒序浏览
pthread_cond_signal()的具体位置?
我在《linux下的多线程编程》http://www.fanqiang.com/a4/b8/20010811/0905001105.html中看到:

pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间,
不然有可能造成无限制的等待。我感觉这这种调用方式是对的,但为什么不这样调用就有可能造成无限制等待,还不是很清楚????

在这个地方看到了符合这个规则的调用:
http://www.ccert.edu.cn/forum/show.php?pub_id=379&type_id=1
********************************************begin
为了判断所有线程已经终止而又不用pthread_join,只好又引入另外一个pthread同步对象:条件变量.
/* current working threads number */
static int curnum = 0;
/* mutex lock for curnum */
static pthread_mutex_t mutex_curnum = PTHREAD_MUTEX_INITIALIZER;
/* cond for curnum */
static pthread_cond_t cond_curnum = PTHREAD_COND_INITIALIZER;

变量curnum代表当前活动线程数,在线程scan函数结尾增加一下代码:
pthread_mutex_lock(&mutex_curnum);
if (!--curnum)
pthread_cond_signal(&cond_curnum);
pthread_mutex_unlock(&mutex_curnum);
return NULL;
每个线程终止时把curnum减1,如果curnum等0,那么通知main所有线程都已
终止. main在创建完线程后就已以下代码阻塞在cond_curnum上:
pthread_mutex_lock(&mutex_curnum);
while(curnum)
pthread_cond_wait(&cond_curnum,&mutex_curnum);
pthread_mutex_unlock(&mutex_curnum);
********************************************end


但我在很多例子程序中。都看到
pthread_mutex_lock()
...
pthread_mutex_unlock()
pthread_cond_signal()

例如POSIX 线程详解,第 3 部分
http://www-900.ibm.com/developerWorks/cn/linux/thread/posix_thread3/index.shtml
里的例子程序,需要下载
http://www-900.ibm.com/developerWorks/cn/linux/thread/posix_thread3/thread-3.tar.gz

解开在workcrew.c中,72行开始:
********************************************begin
  pthread_mutex_lock(&cq.control.mutex);
  queue_put(&cq.cleanup,(node *) mynode);
  pthread_mutex_unlock(&cq.control.mutex);
  pthread_cond_signal(&cq.control.cond);
********************************************end

已经糊涂了。谁能解惑一下。
按我自己的理解,同意前一种情况。

论坛徽章:
0
2 [报告]
发表于 2004-03-18 22:46 |只看该作者

pthread_cond_signal()的具体位置?

自己up一下

论坛徽章:
0
3 [报告]
发表于 2004-03-19 02:07 |只看该作者

pthread_cond_signal()的具体位置?

"pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间, "
这个做法有个问题,举个例子

简单假设线程1、2,curnum 值为 1, 语句执行顺序如下:
  1.                                                    
  2. T2-->;pthread_mutex_lock(&mutex_curnum);              
  3. T2-->;while(curnum)                                   
  4. T2-->;  pthread_cond_wait(&cond_curnum,&mutex_curnum);/*T2解锁,睡眠,等信号*/
  5. T1-->;pthread_mutex_lock(&mutex_curnum);              /*轮T1运行,T1上锁*/                                                   
  6. T1-->;if (!--curnum)                                  /*条件成立*/
  7. T1-->;    pthread_cond_signal(&cond_curnum);          /*T1向线程T2发信号*/
  8. T2-->;pthread_cond_wait(&cond_curnum,&mutex_curnum);  /*T1时间片用完,换T2执行,但发觉不能上锁,因为T1持有锁*/                                                      
  9. T1-->;pthread_mutex_unlock(&mutex_curnum);            /*T1解锁*/
复制代码
                                                   
                                                                                                         
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
问题在于一个条件变量和一个互斥锁关联,
一个线程在持有锁的情况下调用pthread_cond_signal(),
则等待条件的线程有可能得不到锁。

就上面的特定例子来,配合每条语句的执行顺序,
虽然T1调用了pthread_cond_signal(), 但是T2 100%不能获得锁。

《UNIX网络编程第2卷:进程间通信》提了一个改进方法

  1. pthread_mutex_lock();
  2. 判断是否别个线程等待的条件发生,是的话设 "发生标志" 为 "是";
  3. pthread_mutex_unlock();
  4. if (发生标志 == 是)
  5. {
  6.     pthread_cond_signal(...);
  7. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2010-07-17 00:42 |只看该作者
不同的位置有不同的优缺点,根据应用情况自己选择。加锁后发信号,容易把等待线程饿死。解锁后发信号,有个时间窗,有可能条件已经变化了

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
5 [报告]
发表于 2010-07-17 19:14 |只看该作者
pthread_cond_signal()的具体位置?
pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间,
flytod 发表于 2004-03-15 14:13



    错了,是pthread_cond_wait()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间,
pthread_cond_signal()必须要放在pthread_mutex_unlock()之后。

论坛徽章:
0
6 [报告]
发表于 2010-07-20 13:02 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
7 [报告]
发表于 2010-07-20 13:35 |只看该作者
pthread_cond_wait()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间,是因为pthread_cond_wait()要先unlock 线程信号到达后再lock 然后返回。

论坛徽章:
0
8 [报告]
发表于 2010-07-20 14:16 |只看该作者
pthread_cond_wait必须放在pthread_mutex_lock和pthread_mutex_unlock之间,因为他要根据共享变量的状态来觉得是否要等待,而为了不永远等待下去所以必须要在lock/unlock队中
共享变量的状态改变必须遵守lock/unlock的规则

pthread_cond_signal即可以放在pthread_mutex_lock和pthread_mutex_unlock之间,也可以放在pthread_mutex_lock和pthread_mutex_unlock之后,但是各有有缺点。

之间:
pthread_mutex_lock
    xxxxxxx
pthread_cond_signal
pthread_mutex_unlock
缺点:在某下线程的实现中,会造成等待线程从内核中唤醒(由于cond_signal)然后又回到内核空间(因为cond_wait返回后会有原子加锁的行为),所以一来一回会有性能的问题。但是在LinuxThreads或者NPTL里面,就不会有这个问题,因为在Linux 线程中,有两个队列,分别是cond_wait队列和mutex_lock队列, cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用返回到用户空间,不会有性能的损耗。
所以在Linux中推荐使用这种模式。

之后:
pthread_mutex_lock
    xxxxxxx
pthread_mutex_unlock
pthread_cond_signal
优点:不会出现之前说的那个潜在的性能损耗,因为在signal之前就已经释放锁了
缺点:如果unlock和signal之前,有个低优先级的线程正在mutex上等待的话,那么这个低优先级的线程就会抢占高优先级的线程(cond_wait的线程),而这在上面的放中间的模式下是不会出现的。

所以,在Linux下最好pthread_cond_signal放中间,但从编程规则上说,其他两种都可以

论坛徽章:
0
9 [报告]
发表于 2010-07-20 23:01 |只看该作者
楼上的才是大师,我理解的比较肤浅,受教了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP