glib线程实践:GCond和GMutex

前言

        如果使用多线程,就会涉及到并发问题,讨论并发问题。必然涉及到互斥与同步。

一 GMutex

相关的函数

初始化函数

void
g_mutex_init (GMutex *mutex);

上锁函数

void
g_mutex_lock (GMutex *mutex);

解锁函数

gboolean
g_mutex_trylock (GMutex *mutex);

g_mutex_clear ,这个函数,帮助信息上说,如果当前互斥锁处于锁定的状态,调用它会导致未知的事情发生。

g_mutex_clear ()

void
g_mutex_clear (GMutex *mutex);
Frees the resources allocated to a mutex with g_mutex_init().

This function should not be used with a GMutex that has been statically allocated.

Calling g_mutex_clear() on a locked mutex leads to undefined behaviour.

Sine: 2.32

Parameters

mutex
an initialized GMutex

写一段测试代码

#include <glib.h>
#include <gtimer.h>
#include <stdlib.h>

static int count = 0;
GMutex mutex;
gpointer my_thread_01(gpointer data)
{
	int i = 0;
	while(i < 1000){
		i++;
		g_mutex_lock(&mutex);
		count++;
		g_mutex_unlock(&mutex);
	}
	while(1){
		g_usleep(1000);
	}
}
gpointer my_thread_02(gpointer data)
{
	int i = 0;
	while(i < 1000){
		i++;
		g_mutex_lock(&mutex);
		count++;
		g_mutex_unlock(&mutex);
	}
	while(1){
		g_usleep(1000);
	}
}
gpointer my_thread_03(gpointer data)
{
	int i = 0;
	g_usleep(1000*1000);
	g_print("count = %d\n",count);
	while(1){
		g_usleep(1000);
	}
}
int main(void)
{
	g_mutex_init (&mutex);
	g_thread_new("my_thread_01",my_thread_01,NULL);
	g_thread_new("my_thread_02",my_thread_02,NULL);
	g_thread_new("my_thread_03",my_thread_03,NULL);
	
	while(1){
		g_usleep(1000);
	}
	return 0;
}

运行结果:好意外的输出了2000

使用pstree命令,毫无意外的看到了3个子线程。

root@ATK-IMX6U:~# pstree -p 19844
app(19844)─┬─{my_thread_01}(19845)
           ├─{my_thread_02}(19846)
           └─{my_thread_03}(19847)
root@ATK-IMX6U:~#

如果在线程中添加如下代码

g_print("%d :%d\n",getppid(),getpid());

打印的内容如下:

16451 :24948

        使用pstree查看16451的子进程,如下所示,这说明,虽然线程确实有一个单独的进程号,但是使用getpid的时候还是打印app本身的进程号。

root@ATK-IMX6U:~# pstree -p 16451
sh(16451)─┬─app(24948)─┬─{my_thread_01}(24949)
          │            ├─{my_thread_02}(24950)
          │            └─{my_thread_03}(24951)
          └─pstree(25145)
root@ATK-IMX6U:~#

下面这种在一个线程加锁,在另一个线程解锁也是合法的。

static int count = 0;
GMutex mutex;
gpointer my_thread_01(gpointer data)
{
	g_mutex_lock(&mutex);
	while(1){
		g_usleep(1000);
	}
}
gpointer my_thread_02(gpointer data)
{

	g_usleep(1000);

	g_mutex_unlock(&mutex);
	while(1){
		g_usleep(1000);
	}
}

二 GCond

初始化函数

void
g_cond_init (GCond *cond);

等待一个信号量

void
g_cond_wait (GCond *cond,
             GMutex *mutex);

gboolean
g_cond_wait_until (GCond *cond,
                   GMutex *mutex,
                   gint64 end_time);

        下面是一个官方例程:等待5秒,如果超时,g_cond_wait_until返回FALSE;end_time的值是当前的时间微秒数加上需要超时的时间微秒数。

#define G_TIME_SPAN_SECOND              (G_GINT64_CONSTANT (1000000))
gpointer
pop_data_timed (void)
{
  gint64 end_time;
  gpointer data;

  g_mutex_lock (&data_mutex);

  end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
  while (!current_data)
    if (!g_cond_wait_until (&data_cond, &data_mutex, end_time))
      {
        // timeout has passed.
        g_mutex_unlock (&data_mutex);
        return NULL;
      }

  // there is data for us
  data = current_data;
  current_data = NULL;

  g_mutex_unlock (&data_mutex);

  return data;
}

释放信号量

void
g_cond_signal (GCond *cond);

void
g_cond_broadcast (GCond *cond);

测试代码如下:

#include <glib.h>
#include <gtimer.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

static int count = 0;
GMutex mutex;
GCond cond;
char buf[1024];
gpointer my_thread_01(gpointer data)
{
	
	while(1){
		g_mutex_lock(&mutex);
		g_cond_wait(&cond,&mutex);
		printf("buf = %s\n",buf);
		memset(buf,0,sizeof(buf));
		g_mutex_unlock(&mutex);
	}
}
gpointer my_thread_02(gpointer data)
{
	g_usleep(1);
	while(1){
		g_mutex_lock(&mutex);
		g_print("wait for input:");
		//while(strlen(buf) == 0){
			scanf("%s",buf);
		//}
		g_print("send a signal:%s\n",buf);
		//g_cond_broadcast(&cond);
		g_cond_signal(&cond);
		g_print("send a signal over\n",buf);
		g_mutex_unlock(&mutex);	
		
		g_usleep(1000);
	}
}

int main(void)
{
	g_mutex_init (&mutex);
	g_cond_init(&cond);
	memset(buf,0,sizeof(buf));
	g_thread_new("my_thread_01",my_thread_01,NULL);
	g_thread_new("my_thread_02",my_thread_02,NULL);
	
	while(1){
		g_usleep(1000);
	}
	return 0;
}

执行效果:输入hello,线程01会获得信号,并输出hello,

        在线程02函数运行后首先延时1微秒,如果不加延时,线程02先运行,线程01就获得不到锁,就运行不到g_cond_wait,就得不到输入端第一个字符串。

root@ATK-IMX6U:~# ./app
wait for input:hello
send a signal:hello
send a signal over
buf = hello
wait for input:

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千册

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值