关于glib中的线程demo之一

来源:互联网 发布:linux桌面系统 编辑:程序博客网 时间:2024/06/05 14:29
#include <glib.h>static GMutex *mutex = NULL;static gboolean t1_end = FALSE;static gboolean t2_end = FALSE;typedef struct _Arg Arg;struct _Arg{GMainLoop* loop;gint max;};voidrun_1(Arg *arg){int i ;for(i=0; i<arg->max; i++){if(g_mutex_trylock(mutex) == FALSE){//g_print("%d : thread 2 locked the mutex \n", i);g_print("%d :线程2锁定了互斥对象\n", i);g_mutex_unlock(mutex);}else{g_usleep(10);}}t1_end = TRUE;}voidrun_2(Arg *arg){int i;for(i=0; i<arg->max; i++){if(g_mutex_trylock(mutex) == FALSE){//g_print("%d : thread 1 locked mutex \n", i);g_print("%d :线程1锁定了互斥对象\n", i);g_mutex_unlock(mutex);}else{g_usleep(10);}}t2_end = TRUE;}void run_3(Arg *arg){for(;;){if(t1_end && t2_end){g_main_loop_quit(arg->loop);break;}}}intmain(int argc, char *argv[]){GMainLoop *mloop;Arg *arg;if(!g_thread_supported())g_thread_init(NULL);mloop = g_main_loop_new(NULL, FALSE);arg = g_new(Arg, 1);arg->loop = mloop;arg->max = 11;mutex = g_mutex_new();g_thread_create(run_1, arg, TRUE, NULL);g_thread_create(run_2, arg, TRUE, NULL);g_thread_create(run_3, arg, TRUE, NULL);g_main_loop_run(mloop);g_print("线程3退出事件循环\n");g_mutex_free(mutex);g_print("释放互斥对象\n"); g_free(arg);g_print("释放参数所用的内存\n");}

 

Makefile文件如下:

CC = gccall:$(CC) `pkg-config --cflags --libs glib-2.0 gthread-2.0` loop.c -o loop

 

下面为输出结果:

0 :线程1锁定了互斥对象
1 :线程2锁定了互斥对象
2 :线程1锁定了互斥对象
3 :线程2锁定了互斥对象
4 :线程1锁定了互斥对象
5 :线程2锁定了互斥对象
6 :线程1锁定了互斥对象
7 :线程2锁定了互斥对象
8 :线程1锁定了互斥对象
9 :线程2锁定了互斥对象
10 :线程1锁定了互斥对象
线程3退出事件循环
释放互斥对象
释放参数所用的内存

以上例程创建了三个线程,其中run_1和run_2操作互斥对象,run_3检索前两个线程是否结束,如结束的话,则执行g_main_loop_quit退出事件循环。由于线程的运行是不确定的,所以不一定每次都是这一输出结果。

首先定义一个结构类型来保存创建的事件循环的对象指针和线程运行时的最多循环次数,一般情况下,如果为此数据结构来分配内存的话,用Arg *arg =(Arg*)malloc(sizeof(Arg));,释放时用free(arg);,这种传统的做法曾经让很多C语言的初学者头痛,尤其是需要多次操作的时候,GLib中提供了类似的函数g_malloc和g_free,最好用的方法是其将g_malloc函数封装成了宏g_new,这个宏有两个参数,第一个是结构类型,第二个是要分配结构的数量,这段代码中只用到了一个Arg数据结构,所以是g_new(Arg,1)。在程序结束时用g_free来释放。

在线程初始化时,首先是判断线程是否初始化的函数g_thread_supported,如果其返回FALSE则表明线程并未初始化,这时必须用g_thread_init来初始化,这是较明智的做法。

事件循环GMainLoop在用g_main_loop_new创建之后并不马上运行,用g_main_loop_run运行后,还要用g_main_loop_quit退出,否则循环将一直运行下去,这两个函数的参数都是GMainLoop型的指针,在主函数中并未直接运行g_main_loop_quit,而是把它放在线程的函数中了,这一点需读者注意。