【问题标题】:A implement of pthread_cond_wait and pthread_cond_signal , any side-effect?pthread_cond_wait 和 pthread_cond_signal 的实现,有什么副作用吗?
【发布时间】:2012-01-11 07:01:14
【问题描述】:

我的环境是Linux,使用pthreads,用gcc编译。

我有 3 个线程作为接收套接字数据的套接字线程, thread1 和 thread2 每秒大约 1500 行, thread3 每秒将接收 400 行, 在thread1、thread2、thread3中,我使用mutex_lock来保护全局变量, 这样thread4获取这些全局变量是正确的,当然thread4使用 mutex_lock 也是如此。

线程1:

    Pthread_mutex_lock(&Mutex1);
    iGlobal1 = iGlobal1 + 1;    
    Pthread_mutex_unlock(&Mutex1);

线程2:

 Pthread_mutex_lock(&Mutex2);
 iGlobal2 = iGlobal2 + 1;    
 Pthread_mutex_unlock(&Mutex2);

线程3:

 Pthread_mutex_lock(&Mutex3);
 iGlobal3 = iGlobal3 + 1;    
 Pthread_mutex_unlock(&Mutex3);

线程4:

while(1)
{
    Pthread_mutex_lock(&Mutex1);
    ilocal1 = iGlobal1;
    Pthread_mutex_unlock(&Mutex1);

    Pthread_mutex_lock(&Mutex2);
    ilocal2 = iGlobal2;
    Pthread_mutex_unlock(&Mutex2);

    Pthread_mutex_lock(&Mutex3);
    ilocal3 = iGlobal3;
    Pthread_mutex_unlock(&Mutex3);

    DoSomething(ilocal1,ilocal2,ilocal3);
}//while 

在我看来Thread4可以更高效,因为如果thread4执行太频繁, 它消耗大量cpu,并且mutex_lock影响thread1,thread2和thread3...... 所以我认为使用 pthread_cond_signal 会更好,如下所示:

线程1:

 Pthread_mutex_lock(&Mutex1);
 iGlobal1 = iGlobal1 + 1 ;    
 pthread_cond_signal(&condxx);
 Pthread_mutex_unlock(&Mutex1);

线程2:

 Pthread_mutex_lock(&Mutex2);
 iGlobal2 = iGlobal2 + 1 ;   
 pthread_cond_signal(&condxx);
 Pthread_mutex_unlock(&Mutex2);

线程3:

 Pthread_mutex_lock(&Mutex3);
 iGlobal3 = iGlobal3 + 1 ;    
 pthread_cond_signal(&condxx);
 Pthread_mutex_unlock(&Mutex3);

线程4:

while(1)
{

    pthread_cond_wait(&condxx, mutexx);

    Pthread_mutex_lock(&Mutex1);
    ilocal1 = iGlobal1;
    Pthread_mutex_unlock(&Mutex1);

    Pthread_mutex_lock(&Mutex2);
    ilocal2 = iGlobal2;
    Pthread_mutex_unlock(&Mutex2);

    Pthread_mutex_lock(&Mutex3);
    ilocal3 = iGlobal3;
    Pthread_mutex_unlock(&Mutex3);

    DoSomething(ilocal1,ilocal2,ilocal3);
}//while 

因为 pthread_cond_signal 不会对信号进行排队,所以它在 thread1, thread2, thread3 每次接收套接字数据时触发 pthread_cond_signal, 并且 thread4 将被阻塞在 pthread_cond_wait(&condxx, mutexx) 直到 get pthread_cond_signal,这将节省 cpu 时间,并且不会影响 thread1、thread2、thread3,因为使用的 mutex_lock 更少!

我的想法是,使用 pthread_cond_wait 表现得像 usleep, 但是当数据到达时,thread4不会错过!

请问,我做的有什么副作用吗?欢迎任何建议

【问题讨论】:

  • thread4 中的 DoSomething() 是否要求所有 3 个线程都更改了各自的全局或仅更改一个? thread4 是否以任何方式更改全局变量?全局变量是否不仅仅是内置类型并且相对较小?换句话说,如果 DoSomething() 只是更新一个 GUI 计数器或一些类似的操作,您可能能够一起免除锁,而只需将线程 1、2、3 写入管道。线程 4 挂在读取的管道上并执行其操作。
  • 谢谢你,Duck,一旦 Thread1,thread2,threa3 之一发生变化,它需要调用 DoSomething ,DoSomething 不会改变全局变量,但是 Dosomething 需要复杂的计算,完成的成本时间,我认为管道是个好主意,谢谢你的好建议!
  • 转念一想,在 Dosomethin 执行过程中,同时 Thread1 收到了 3 个数据,thread2 收到了 5 个数据,thread3 收到了 1 个数据,我只喜欢只使用第 3 个数据thread1 的第 5 个数据,thread2 的第 5 个数据,thread3 中的第 1 个数据,一起填写 DoSomething ,在我的情况下使用管道不是一个好主意!

标签: c pthreads mutex


【解决方案1】:

我认为您使线程 4 更高效的方法是一种很好的方法。如果只有线程 1(生产者)和线程 4(消费者),那么您的方法是让线程 4 有效地等待线程 1 提供数据的标准方法。这里的问题是存在多个生产者线程(线程 2 和 3)。

pthread_cond_signal() 的手册页说,发出没有线程等待的条件的信号将无效,因此在线程 1、2 和 3 同时发出信号 condxx 的情况下(如在多处理器系统上) ,内核将有一个调用pthread_cond_signal()实际上解除阻塞线程4,而其他两个将不起作用。

换句话说,我认为你的方法会奏效。等待由内核管理的数据(pthread_cond_wait()select() 等)总是比循环轮询(你的usleep() 想法)更好。

话虽如此,您的示例中缺少一些关键的代码片段。 mutexx 需要在调用pthread_cond_wait() 之前被锁定,并且必须在调用pthread_cond_signal() 前后被锁定和解锁。 This web page 有一个与您的用例非常相似的示例,并演示了正确的锁定技术。

【讨论】:

  • 谢谢!!你帮了很多忙!
  • 没问题。我很乐意提供帮助。顺便说一句,在 Stack Overflow 上,表达感激之情的一个好方法是投票和/或接受你喜欢的答案。
  • 我不知道为什么,我点击了“投票”,但什么也没发生,这真的很困扰我......我会花时间弄清楚!!
  • 哦...投票需要15声望...我只有一半,但现在我知道如何接受答案了,谢谢!!
猜你喜欢
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
  • 2012-10-27
相关资源
最近更新 更多