关于gtk的GCond

下面两个函数:
void        g_cond_signal                   (GCond *cond);
void        g_cond_wait                     (GCond *cond,  GMutex *mutex);
用于进行线程同步。
mutex 是“mutual exclusion”(互斥)的英文缩写,用来保证线程对于共享数据的独占访问。


下面是Glib Reference Manual里面的一个例子:
  1. GCond* data_cond = NULL;   /* Must be initialized somewhere */
  2. GMutex* data_mutex = NULL; /* Must be initialized somewhere */
  3. gpointer current_data = NULL;

  4. void push_data (gpointer data)
  5. {
  6.   g_mutex_lock (data_mutex);
  7.   current_data = data;
  8.   g_cond_signal (data_cond);
  9.   g_mutex_unlock (data_mutex);
  10. }

  11. gpointer pop_data ()
  12. {
  13.   gpointer data;

  14.   g_mutex_lock (data_mutex);
  15.   while (!current_data)
  16.       g_cond_wait (data_cond, data_mutex);
  17.   data = current_data;
  18.   current_data = NULL;
  19.   g_mutex_unlock (data_mutex);
  20.   return data;
  21. }
复制代码


当调用了pop_data()的时候,如果current_data==NULL,那么pop_data()处于wait状态,直到其它线程调用了push_data(),这时push_data()会发送一个signal(g_cond_signal),然后把pop_data()激活。


问题:

这里是不是只有push一个元素的时候才能pop一个啊?如果我连续push两个,而在这之间并没有调用pop,那么g_cond_signal发送到Data_cond的信号怎么处理?还有就是这里的Data_mutex是在lock什么东西?


解答:

当调用了pop_data()的时候,如果current_data==NULL,那么调用了pop_data()函数的线程将处于wait状态,直到其它线程调用了push_data()。这时,push_data()会添加新的数据并发送一个signal通知这一情况。原来处于等待状态的线程在收到信号后解除 g_cond_wait() 等待状态,然后执行 while 循环;由于此时循环条件已经不成立了(current_data!=NULL说明有了有效数据),while 循环结束,从而结束线程的等待状态,程序会取得新的数据供使用。

只要一直有数据(current_data!=NULL),在pop_data() 的时候 while 循环的条件就不成立,从而不会进入等待状态,可以多次pop_data(),直到数据为空为止(current_data==NULL)。当然,如果共享的数据只有一个,那就在pop_data()之后只有等到push_data()添加新的数据才行了。

如果用g_cond_signal()多次发送信号而没有被接收的话,这些信号将被丢弃。


另外,关于g_cond_wait()可见:http://developer.gnome.org/glib/2.31/glib-Threads.html#g-cond-wait



posted @ 2012-08-31 18:43  夏至冬末  阅读(728)  评论(0编辑  收藏  举报